转载于:https://blog.csdn.net/swordmanwk/article/details/42519275
aaa(ASCII adjust after addition)指令,是BCD指令集中的一个指令,用于在两个未打包的BCD值相加后,调整al和ah寄存器的内容。
BCD(Binary-coded decimal)数是指2进制编码的10进制数,占据一个字节的低4位,只有0-9是有效值。
AAA指令做两件事情:
如果al的低4位是在0到9之间,保留低4位,清除高4位,如果al的低4位在10到15之间,则通过加6,来使得低4位在0到9之间,然后再对高4位清零。
如果al的低4位是在0到9之间,ah值不变,CF和AF标志清零,否则,ah=ah+1,并设置CF和AF标志。
下面看一个示例程序:
- section .data
- EditBuff: db 'abcdefghijklm',10
- BUFFERLEN equ $-EditBuff
- FILLCHR equ 35 ;'#'
- section .text
- WriteStr:
- push eax ; Save pertinent registers
- push ebx
- mov eax,4 ; Specify sys_write call
- mov ebx,1 ; Specify File Descriptor 1: Stdout
- int 80H ; Make the kernel call
- pop ebx ; Restore pertinent registers
- pop eax
- ret ; Go home
- global _start
- _start:
- nop
- mov ecx,EditBuff
- mov edx,BUFFERLEN
- call WriteStr
- mov edi,EditBuff
- mov ecx,BUFFERLEN-1
- mov al,'1' ; Start ruler with digit '1'
- DoChar: stosb ; Note that there's no REP prefix!
- add al,'1' ; Bump the character value in AL up by 1
- aaa ; Adjust AX to make this a BCD addition
- add al,'0' ; Make sure we have binary 3 in AL's high nybble
- loop DoChar ; Go back & do another char until ECX goes to 0
- mov ecx,EditBuff
- mov edx,BUFFERLEN
- call WriteStr
- Exit: mov eax,1 ; Code for Exit Syscall
- mov ebx,0 ; Return a code of zero
- int 80H ; Make kernel call
程序分析:
mov edi,EditBuff //edi = EditBuff
mov ecx,BUFFERLEN-1 //ecx= BUFFERLEN-1,这样可以不覆盖最后一个换行符
mov al,'1' //al = ‘1’,1的ASCII码值是0x31,低4位恰好是有效的BCD值
DoChar: stosb //edi=al
add al,'1' //两个ASCII码值相加。
aaa //使用aaa指令进行调整,使得低4位是有效的BCD值。只有’9’加’1’会形成无效BCD数(10),调整后al会等于0,其他都不需要调整低4位,只是简单对高4位清零。
add al,'0' //要把数字转换成ASCII码,需要再把’0’加回来,例如9+’0’=’9’。
loop DoChar //ecx=ecx-1,如果ecx不等于0,跳转到DoChar继续循环。ecx=13,所以会填充字符13次。
makefile文件内容:
- aaademo: aaademo.o
- ld -o aaademo aaademo.o
- aaademo.o: aaademo.asm
- nasm -f elf -g -F stabs aaademo.asm -l aaademo.lst
测试:
- [root@bogon aaademo]# make
- nasm -f elf -g -F stabs aaademo.asm -l aaademo.lst
- ld -o aaademo aaademo.o
- [root@bogon aaademo]# ./aaademo
- abcdefghijklm
- 1234567890123