Обычно числовые данные в Ассемблере представлены в двоичной системе. Арифметические инструкции работают с двоичными данными. Когда числа отображаются на экране или вводятся с клавиатуры, они имеют ASCII-форму.
Представление чисел в Ассемблере
До сих пор мы конвертировали входные данные из ASCII-формы в двоичную систему для выполнения арифметических операций, а затем результат обратно в ASCII-форму. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
section .text global _start ; должно быть объявлено для использования gcc _start: ; сообщаем линкеру входную точку mov eax,'3' sub eax, '0' mov ebx, '4' sub ebx, '0' add eax, ebx add eax, '0' mov [sum], eax mov ecx,msg mov edx, len mov ebx,1 ; файловый дескриптор (stdout) mov eax,4 ; номер системного вызова (sys_write) int 0x80 ; вызов ядра mov ecx,sum mov edx, 1 mov ebx,1 ; файловый дескриптор (stdout) mov eax,4 ; номер системного вызова (sys_write) int 0x80 ; вызов ядра mov eax,1 ; номер системного вызова (sys_exit) int 0x80 ; вызов ядра section .data msg db "The sum is:", 0xA,0xD len equ $ - msg segment .bss sum resb 1 |
Результат выполнения программы:
The sum is:
7
Программирование на ассемблере позволяет более эффективно обрабатывать числа в двоичном виде. Десятичные числа могут быть представлены в следующих двух формах:
ASCII-форма;
BCD-форма (или «Двоично-десятичный код»).
ASCII-представление
В ASCII-представлении десятичные числа хранятся в виде строки ASCII-символов. Есть 4 инструкции для обработки чисел в ASCII-представлении:
AAA (англ. «Adjust After Addition») — настроить после добавления;
AAS (англ. «Adjust After Subtraction») — настроить после вычитания;
AAM (англ. «Adjust After Multiplication») — настроить после умножения;
AAD (англ. «Adjust After Division») — настроить после деления.
Эти инструкции не принимают никаких операндов и предполагают, что требуемый операнд находится в регистре AL
.
В следующем примере мы будем использовать инструкцию AAS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
section .text global _start ; должно быть объявлено для использования gcc _start: ; сообщаем линкеру входную точку sub ah, ah mov al, '9' sub al, '3' aas or al, 30h mov [res], ax mov edx,len ; длина сообщения mov ecx,msg ; сообщение для вывода на экран mov ebx,1 ; файловый дескриптор (stdout) mov eax,4 ; номер системного вызова (sys_write) int 0x80 ; вызов ядра mov edx,1 ; длина сообщения mov ecx,res ; сообщение для вывода на экран mov ebx,1 ; файловый дескриптор (stdout) mov eax,4 ; номер системного вызова (sys_write) int 0x80 ; вызов ядра mov eax,1 ; номер системного вызова (sys_exit) int 0x80 ; вызов ядра section .data msg db 'The Result is:',0xa len equ $ - msg section .bss res resb 1 |
Результат выполнения программы:
The Result is:
6
BCD-представление
Существует два типа BCD-представления:
распакованное BCD-представление;
упакованное BCD-представление.
В распакованном BCD-представлении каждый байт хранит двоичный эквивалент каждой десятичной цифры числа. Четыре инструкции настройки ASCII: AAA, AAS, AAM и AAD; также могут использоваться с распакованным BCD-представлением.
В упакованном BCD-представлении каждая цифра сохраняется с использованием 4 бит. Две десятичные цифры упаковываются в 1 байт. Есть две инструкции для обработки этих чисел:
DAA (англ. «Decimal Adjust After Addition») — десятичная настройка после добавления;
DAS (англ. «Decimal Adjust After Subtraction») — десятичная настройка после вычитания.
Обратите внимание, что в упакованном BCD-представлении отсутствует поддержка операций умножения и деления.
В следующей программе мы выполним операцию сложения двух 5-значных десятичных чисел и выведем на экран их сумму:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
section .text global _start ; должно быть объявлено для использования gcc _start: ; сообщаем линкеру входную точку mov esi, 4 ; указываем на крайнюю правую цифру mov ecx, 5 ; количество цифр clc add_loop: mov al, [num1 + esi] adc al, [num2 + esi] aaa pushf or al, 30h popf mov [sum + esi], al dec esi loop add_loop mov edx,len ; длина сообщения mov ecx,msg ; сообщение для вывода на экран mov ebx,1 ; файловый дескриптор (stdout) mov eax,4 ; номер системного вызова (sys_write) int 0x80 ; вызов ядра mov edx,5 ; длина сообщения mov ecx,sum ; сообщение для вывода на экран mov ebx,1 ; файловый дескриптор (stdout) mov eax,4 ; номер системного вызова (sys_write) int 0x80 ; вызов ядра mov eax,1 ; номер системного вызова (sys_exit) int 0x80 ; вызов ядра section .data msg db 'The Sum is:',0xa len equ $ - msg num1 db '12345' num2 db '23456' sum db ' ' |
Результат выполнения программы:
The Sum is:
35801