汇编语言 数字

数值数据通常用二进制表示。算术指令对二进制数据进行操作。当数字显示在屏幕上或从键盘输入时,它们是 ASCII 形式。到目前为止,我们已经将该输入数据以 ASCII 形式转换为二进制以进行算术计算,并将结果转换回二进制。

下面看一个实例:

  1. section .text
  2. global _start ;必须声明 gcc
  3. _start: ;告诉链接器入口点
  4. mov eax,'3'
  5. sub eax, '0'
  6. mov ebx, '4'
  7. sub ebx, '0'
  8. add eax, ebx
  9. add eax, '0'
  10. mov [sum], eax
  11. mov ecx,msg
  12. mov edx, len
  13. mov ebx,1 ;文件描述 (stdout)
  14. mov eax,4 ;系统调用号 (sys_write)
  15. int 0x80 ;调用内核
  16. mov ecx,sum
  17. mov edx, 1
  18. mov ebx,1 ;文件描述 (stdout)
  19. mov eax,4 ;系统调用号 (sys_write)
  20. int 0x80 ;调用内核
  21. mov eax,1 ;系统调用号 (sys_exit)
  22. int 0x80 ;调用内核
  23. section .data
  24. msg db "The sum is:", 0xA,0xD
  25. len equ $ - msg
  26. segment .bss
  27. sum resb 1

结果如下:

  1. The sum is:
  2. 7

然而,这种转换有性能损耗,汇编语言编程支持以更有效的方式处理二进制形式的数字。

十进制数字可以用两种形式:

  • ASCII 格式

  • BCD 或二进制编码十进制形式


ASCII 表示

在 ASCII 表示中,十进制数字存储为 ASCII 字符字符串。

例如,十进制值 1234 存储为:

  1. 31323334H

其中,31H 是 1 的 ASCII 值,32H 是 2 的 ASCII 值,依此类推。

有 4 种指令用于处理 ASCII 表示形式的数字-

  • AAA - 加法后 ASCII 调整

  • AAS - 减法后的 ASCII 调整

  • AAM - 乘法后 ASCII 调整

  • AAD - 除法前 ASCII 调整

这些指令不使用任何操作数,并假定所需的操作数位于 AL 寄存器中。

比如下面的实例:

  1. section .text
  2. global _start ;必须声明 gcc
  3. _start: ;告诉链接器入口点
  4. sub ah, ah
  5. mov al, '9'
  6. sub al, '3'
  7. aas
  8. or al, 30h
  9. mov [res], ax
  10. mov edx,len ;消息长度
  11. mov ecx,msg ;消息
  12. mov ebx,1 ;文件描述 (stdout)
  13. mov eax,4 ;系统调用号 (sys_write)
  14. int 0x80 ;调用内核
  15. mov edx,1 ;消息长度
  16. mov ecx,res ;消息
  17. mov ebx,1 ;文件描述 (stdout)
  18. mov eax,4 ;系统调用号 (sys_write)
  19. int 0x80 ;调用内核
  20. mov eax,1 ;系统调用号 (sys_exit)
  21. int 0x80 ;调用内核
  22. section .data
  23. msg db 'The Result is:',0xa
  24. len equ $ - msg
  25. section .bss
  26. res resb 1

结果如下:

  1. The Result is:
  2. 6

BCD 表示

BCD 表示有两种类型:

  • 未打包的 BCD 表示
  • 打包的 BCD 表示

在未压缩的 BCD 表示形式中,每个字节都存储一个十进制数字的二进制等效项。例如,数字 1234 存储为:

  1. 01 02 03 04H

有两种指令来处理这些数字:

  • AAM - 乘法后 ASCII 调整

  • AAD - 除法前 ASCII 调整

四个 ASCII 调整指令 AAAAASAAMAAD 也可以与未打包的 BCD 表示一起使用。在打包的 BCD 表示中,每个数字使用四位存储。两个十进制数字打包成一个字节。

例如,数字 1234 存储为:

  1. 1234H

有两种指令来处理这些数字:

  • DAA - 加法后的十进制调整

  • DAS - 减后的十进制调整

打包的 BCD 表示形式不支持乘法和除法。


实例

以下程序将两个 5 位十进制数字加起来并显示总和。

  1. section .text
  2. global _start ;必须声明才能使用 gcc
  3. _start: ;告诉链接器入口点
  4. mov esi, 4 ;指向最右边的数字
  5. mov ecx, 5 ;数字位数
  6. clc
  7. add_num:
  8. mov al, [num1 + esi]
  9. adc al, [num2 + esi]
  10. aaa
  11. pushf
  12. or al, 30h
  13. popf
  14. mov [sum + esi], al
  15. dec esi
  16. num add_num
  17. mov edx,len ;消息长度
  18. mov ecx,msg ;消息
  19. mov ebx,1 ;文件描述 (stdout)
  20. mov eax,4 ;系统调用数 (sys_write)
  21. int 0x80 ;调用内核
  22. mov edx,5 ;消息长度
  23. mov ecx,sum ;消息
  24. mov ebx,1 ;文件描述 (stdout)
  25. mov eax,4 ;系统调用数 (sys_write)
  26. int 0x80 ;调用内核
  27. mov eax,1 ;系统调用数 (sys_exit)
  28. int 0x80 ;调用内核
  29. section .data
  30. msg db 'The Sum is:',0xa
  31. len equ $ - msg
  32. num1 db '12345'
  33. num2 db '23456'
  34. sum db ' '

结果如下:

  1. The Sum is:
  2. 35801