Как вывести отрицательное число в ассемблере
Перейти к содержимому

Как вывести отрицательное число в ассемблере

  • автор:

вывод отрицательного числа в ассемблер TASM

Задача: Вывести число -1 на экран.
Почему программный код работает неправильно, хотя должен работать. А стоит изменить регистр на CL начинает работать как надо.
.model small
.data
.stack 80h
.code
start:
mov ax,@data
mov ds,ax
mov al,-1 // меняю здесь mov cl,-1
mov dl,’-‘
mov ah,2
int 21h // добавляю строчку mov al,cl и начинает работать
neg al
mov dl,al
add dl,’0′
int 21h
mov ax,4c00h
int 21h
end start

6. Знак числа в ассемблер 8086

Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS). Числа со знаком и дополнительный код Помимо того, что процессор работает с двоичными числами, эти числа могут быть со знаком или без знака. Если число без знака, то оно просто представляет собой результат перевода десятичного числа в двоичный вид. Все биты в таком числе являются информационными и оно может принимать только неотрицательные значения. Для представления чисел со знаком используется специальное кодирование. Старший бит в этом случае обозначает знак числа. Если знаковый бит равен нулю, то число положительное, иначе — отрицательное. Понятно, что положительное число со знаком будет выглядеть точно так же, как и число без знака. С отрицательными числами чуть сложнее. Исторически для представления отрицательных чисел в компьютерах использовались разные виды кодирования: прямой, обратный и дополнительный код. В настоящее время наиболее часто используется дополнительный код, в том числе и в процессорах x86. Чтобы сделать из положительного числа отрицательное, необходимо проинвертировать все его биты (0 заменяем на 1, а 1 заменяем на 0) и затем к младшему разряду прибавить единицу. Например, представим -5 в дополнительном коде: В обратную сторону переводится точно также. Синтаксис FASM Для записи отрицательного числа в программе на ассемблере используется символ ‘-‘, например: x db -5 Кстати, это работает и с числами в других системах счисления, и даже с символами ?

y db -25h z db -77o k db -101b s db -'a'

Со знаковыми и беззнаковыми числами нужно быть внимательным, потому что только вы знаете, какие числа используются в вашей программе! Процессору абсолютно по барабану, какие данные он обрабатывает, поэтому невнимательность может привести к ошибке. Один и тот же байт может интерпретироваться по-разному, в зависимости от того со знаком число или без. Например, числу со знаком -5 соответствует число без знака 251: Диапазоны значений чисел со знаком и без При программировании на ассемблере (как, впрочем, и на многих других языках) необходимо учитывать ещё один важный момент. А именно — ограничение диапазона представления чисел. Например, если размер беззнаковой переменной равен 1 байт, то она может принимать всего 256 различных значений. Это означает, что мы не сможем представить с её помощью число, больше 255 (11111111_2) . Для такой же переменной со знаком максимальным значением будет 127 (01111111_2) , а минимальным -128 (10000000_2) . Аналогично определяется диапазон для 2- и 4-байтных переменных. Кстати, так как процессор Intel 8086 был 16-битным и обрабатывал за одну команду 16-бит, то 16-битная переменная называется слово (word), а 32-битная — двойное слово (double word, dword). Эти названия сохранились в ассемблере даже для 32-битных процессоров (и в WIN32 API, например). И от них же происходят названия директив dw (Define Word) и dd (Define Dword). Ну а db — это Define Byte. Для наглядности вот табличка диапазонов чисел:

Размер
переменной
Число без знака Число со знаком
min max min max
байт 00000000 11111111 10000000 01111111
0 255 -128 127
слово 00000000 00000000 11111111 11111111 10000000 00000000 01111111 11111111
0 65 535 -32 768 32 767
двойное
слово
0000…0000 1111…1111 1000…0000 0111…1111
0 4 294 967 295 -2 147 483 648 2 147 483 647
и т.д.

Если результат какой-то операции выйдет за пределы диапазона представления чисел, то случится переполнение и результат будет некорректным. (Например, при сложении двух положительных чисел, можно получить отрицательное число!) Поэтому нужно быть внимательным при программировании и предусмотреть обработку таких ситуаций, если они могут возникнуть.

Просмотр 0 веток ответов

Отрицательные числа

Мы разобрались, как в памяти компьютера представлены положительные числа, то есть числа без знака. Но ведь числа бывают и отрицательными, то есть числа со знаком минус. Чтобы применять те же самые байты и слова для представления отрицательных чисел, существует специальная операция, которая называется дополнение до двух. Но прежде чем рассмотреть эту операцию, покажем, как отрицательное число отличить от положительного.

Для того чтобы указать знак числа, достаточно одного разряда (бита). Обычно знаковый бит занимает старший разряд числа. Если старший бит числа равен 0, то число считается положительным. Если старший разряд числа равен 1, то число считается отрицательным. Пример байта со знаком приведён на рис. 2.3.

Разряды Число
7 6 5 4 3 2 1 0
1 0 0 1 0 0 1 0 -110
0 1 1 0 1 1 1 0 +110

Рис. 2.3. Отрицательное число в памяти компьютера.

Как вы успели заметить, для представления числа со знаком требуется использовать старший бит для определения знака числа. Это означает, что этот старший бит уже нельзя использовать для записи самого числа, то есть максимальное значение, которое мы сможем записать в байт, будет уже не 255, а всего 127. Диапазоны возможных значений чисел со знаком приведены в таблице 2.5.

Таблица 2.5. Диапазоны возможных значений чисел со знаком.

Тип числа Диапазон значений Степени двойки
Байт –128…+127 -2 7 …(2 7 – 1)
Слово –32 768…+32 767 -2 15 …(2 15 – 1)
Двойное слово –2 147 483 648…
+2 147 483 647
-2 31 …(2 31 – 1)
Учетверённое слово –9 223 372 036 854 775 808…
+9 223 372 036 854 775 807
-2 63 …(2 63 – 1)

А теперь разберёмся с загадочной операцией дополнение до двух. Для изменения знака числа выполняется инверсия, то есть для числа в двоичном представлении все нули заменяются единицами, а все единицы – нулями. Затем к полученному результату прибавляют 1. Возьмём, например, десятичное число 110 (в двоичной системе это число 01101110). Тогда

Исходное число 0110 1110
Инверсия 1001 0001
Прибавляем 1 1001 0010

Как видим, после выполнения этих преобразований в старшем разряде у нас 1, то есть число отрицательное. А теперь проверим, что это число действительно отрицательное. Как это сделать? Вспомним, что (–110 + 110 = 0). То есть сложение полученных нами двоичных чисел тоже должно дать в результате ноль. Итак

01101110 + 10010010 = 100000000

То есть у нас получилось девятиразрядное число 100000000 (десятичное 256). Однако мы работаем с байтом, а в байте, как известно, только 8 бит (от 0 до 7). То есть единица у нас перешла в 8-й бит, которого в байте попросту нет. То есть для байта это эквивалентно числу 0.

В некоторых источниках дополнение до двух носит название двоичный дополнительный код.

Подведём итоги

Преобразования положительного десятичного числа со знаком в двоичное число выполняется также как и для чисел без знака.

Преобразования отрицательного десятичного числа со знаком в отрицательное двоичное число выполняется при помощи операции дополнение до двух (с использованием двоичного дополнительного кода). То есть сначала число преобразовывается в двоичное, а потом используется двоичный дополнительный код.

Преобразования положительного двоичного числа со знаком (в старшем бите 0) в десятичное число выполняется также как и для чисел без знака.

Преобразование отрицательного двоичного числа (в старшем бите 1) в десятичное число выполняется путём нахождения его дополнительного кода. То есть для двоичного числа 10010010 операция будет следующей:

Исходное число 1001 0010
Инверсия 0110 1101
Прибавляем 1 0110 1110

В итоге получаем число 110, но поскольку в исходном числе старший бит был равен 1, то это отрицательное число, то есть –110.

Как вывести отрицательное число в ассемблере

Нужно к примеру ввести число -7
Если использовать функцию ниже то получиться ввести только одну клавишу .
Как правельнее сделать?
Ну вот я например хочу ввести число нажать Enter и тд. а так получаеться считать одну клавишу

 mov ah, 1 ; ah 

Особый статус
Участник клуба
Регистрация: 24.11.2008
Сообщений: 1,535
А если цифру вычитать из нуля?

Sasha_Smirnov
Посмотреть профиль
Найти ещё сообщения от Sasha_Smirnov

Форумчанин
Регистрация: 18.10.2008
Сообщений: 166
Сообщение от Sasha_Smirnov
А если цифру вычитать из нуля?

да мне просто подскажите, как ввести с клавиатуры отрицательное число.
просто эта функция принимает одно нажатие клавиши и записивает в регистр AL тоисть я могу только кнопку минус " - " а после минуса цифру уже не введу

Последний раз редактировалось Alex1991; 30.10.2010 в 18:18 .
Участник клуба
Регистрация: 02.05.2009
Сообщений: 1,605
ну введите 2 символа. если первый будет минус, то сделайте второй отрицательным числом.

Какой вопрос - такой ответ. Не забываем пользоваться поиском, гуглом.
Помощь в выполнении работ по ассемблеру ICQ:2725322O4

Форумчанин
Регистрация: 18.10.2008
Сообщений: 166
Сообщение от Goodwin98
ну введите 2 символа. если первый будет минус, то сделайте второй отрицательным числом.
а если число будет типа -12, то получиться что я считаю -1
Участник клуба
Регистрация: 15.05.2009
Сообщений: 1,222

ну дак встретили минус, запомнили его например присвоили di единицу, считаете число как положительное, а затем проверяете если di = 1 выполняете neg

Единственное, что ограничивает полет мысли программиста-компилятор
Форумчанин
Регистрация: 18.10.2008
Сообщений: 166
Сообщение от Sparky

ну дак встретили минус, запомнили его например присвоили di единицу, считаете число как положительное, а затем проверяете если di = 1 выполняете neg

Не могли бы вы показать как на коде реализовать ? Вообщем нужно заполнить одномерный массив елемантами, елементы могут также быть отрицательные.
А разве нет такой функции которая запишет елемент после нажатия Enter, ну например ввел -25 нажал ентер и так дальше с другими елементами массива ?

Участник клуба
Регистрация: 15.05.2009
Сообщений: 1,222
нужно кодить это самостоятельно.
Единственное, что ограничивает полет мысли программиста-компилятор
Форумчанин
Регистрация: 31.05.2009
Сообщений: 786

.model small .data str1 db 13,10,'введите первое число: $' str2 db 13,10'введите второе число: $' n1 dw 0 n2 dw 0 buf1 db 13,10,10 dup('$') .stack 256 .code start: mov ax,@data ;настраиваем сегментные регистры mov ds,ax mov es,ax mov dx, offset str1 call InputNumber mov n1,ax mov dx, offset str2 call InputNumber mov n2,ax add ax,n1 lea di,buf1+2 call printdec lea dx,buf1+2 mov ah,9 int 21h ex: mov ax,4c00h ;выход из программы int 21h str2dw proc ;Преобразование строки в число ;на входе ds:si ссылается на ASCIIZ строку, которую нужно преобразовать ; на выходе в ax - число. push bx push dx push si xor bx,bx xor dx,dx ;сумма @lp1: xor ax,ax lodsb ;берем чимвол test al,al ;если это нулей байт, то заканчиваем jz @ex cmp al,'-' ;если минус, то устанавливаем признак минуса jnz @m1 mov bx,1 jmp @lp1 @m1: cmp al,'9' ;Если это не цифра, то пропускаем jnbe @lp1 cmp al,'0' ;Если это не цифра, то пропускаем jb @lp1 sub ax,'0' ;получаем цифровое значение shl dx,1 ;умножаем сумму на 10 add ax, dx shl dx, 2 add dx, ax ;прибавляем текущее значение jmp @lp1 @ex: test bx,bx ;если установлен признак отрицательного числа jz @ex1 neg dx ;то меняем знак @ex1: mov ax,dx pop si pop dx pop bx ret str2dw endp InputNumber proc ; функция выводит на экран сообщение и ожидает ввода числа ; ds:dx - сообщение, которое следует вывести ; возвращает: ; ax - введенное число push dx ; сохраняем регистры push si push di mov ah,9 int 21h mov ah,0ah mov dx,offset buf int 21h ;пользователь вводит в текстовом виде в buf значение элемента массива mov di,offset buf+1 mov al,[di] ;берем длину введенной строки mov ah,0 ;ах=длине inc di ;начало введенной строки в памяти mov si,di ;сохраняем это значение add di,ax ;конец введенной строки в памяти mov [di],byte ptr 0 ;ставим нулевой байт за последним символом строки call str2dw ;преобразовываем строку в значение pop di ;восстанавливаем регистры pop si pop dx ret buf db 8, 10 dup(0) ;принимает строку, введенную с клавиатуры InputNumber endp printdec proc ;преобразование числа из ах в десятичную строку по адресу es:di ;ax - число ;es:di - адрес буфера приемника push cx ;сохраняем регистры push dx push bx mov bx,10 ;основание системы XOR CX,CX ;в сх будет количество цифр в десятичном числе @@m1: XOR dx,dx DIV bx ;делим число на степени 10 PUSH DX ;и сохраняем остаток от деления(коэффициенты при степенях) в стек INC CX TEST AX,AX JNZ @@m1 @@m2: POP AX ADD AL,'0' ;преобразовываем число в ASCII символ STOSb ;сохраняем в буфер LOOP @@m2 ;все цифры pop bx ;восстанавливаем регистры POP dx POP cx RET printdec endp end start end

Помощь с программами:
vk.com/alexcoder1
e-mail: informatik101@mail.ru

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Считывание с файла отрицательных чисел trinki Общие вопросы C/C++ 2 01.10.2010 01:39
Пщдсчет отрицательных чисел в массиве Ehha1234 Паскаль, Turbo Pascal, PascalABC.NET 2 04.06.2010 12:41
Замена отрицательных чисел нулями DasV Помощь студентам 0 30.04.2010 00:42
Перевод отрицательных чисел в двоичную систему ioda1986 Помощь студентам 1 24.02.2010 00:55
Паскаль.Файлы.удаление отрицательных чисел NEMO1991 Помощь студентам 3 06.06.2009 00:38

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *