关于汇编指令aaa的问题

qq_28037887 2015-05-08 09:54:36
指令格式:AAA

指令功能:对2个未组合的BCD码相加后的结果(必须在AL中)进行调整,产生一个正确的BCD码。如果AL低4位>09H或者AF=1,则进行(AL)+06H→(AL),同时(AH)+1→(AH),AL的高4位清0,然后使AF=1,CF=1

标志位影响:只影响AF与CF

注意:此指令通常跟在加法指令之后

而大致实践情况和上面一致,需要说明的是AL低4位>09H和AF=1这两个条件只要有一个(或两个都)满足,AH则+1.
同时实践出另一个奇异之处,就是在AAA的+6时AL可能向AH进位.真是很奇异!
提供以下代码供实践:
mov ax,0fh ;ax=000fh
add al,0eh ;ax=001dh (af=1,低4位>9)
aaa ;ax=0103h 符合低4+6,高4清0,AH+1
mov ax,0efh ;ax=00efh
add al,0eh ;ax=00fdh (af=1,低4位>9)
aaa ; 实际实验结果ax=0203h,理论上:本来AX应和上面一致=0103h(低4+6,高4清0,AH+1),竟然AL+6后还进位1进AH了这是为什么啊??
...全文
1765 4 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
CSDN_1AND0 2015-05-16
  • 打赏
  • 举报
回复
更正: 如此,这个AAA指令的就很明确的呈现在我们面前,它的功能可以说是这样的: 它将先侦测AL低4位是否大于9,AF是否=1。如果AL(低4)>9,或者AF=1,则AL+6→AL,AH带进位+1→AH,置AL高4为0,使AF=1,CF=1,否则AF=0,CF=0。
CSDN_1AND0 2015-05-16
  • 打赏
  • 举报
回复
这个AAA指令的奇异之处,记得是我几年前在这个版参与讨论时发现了,后一直不得其解,鉴于当年很喜欢钻牛角,就记录在某处,后因种种原因,没再接触汇编。今天偶上CSDN,看到了这个问题,感觉很熟悉(其实这个就是摘取我那记录的一段。无妨,学术就是要多探讨,只有多公布,才可多探讨),就看了下,禁不住奇心又起,再在网上搜了下,一种比较靠谱的说法是: mov ax,0efh add al,0eh aaa 这段代码中的0efh和0eh已不是非压缩BCD码(确实是这样),所以AAA后产生的结果不正确也就理所当然了。因为AAA指令是进行非压缩BCD码调整的指令,所以两个不符合非压缩BCD码这一条件要求的数值进行加法操作后,其进行调整不出现正确答案是很正常的。 以上为网上一种比较合理的说法,我基本也以为然。毕竟条件不符,结果不符也就很合理了。 记得在这个版以前有个先辈常告诫的一句话就是“不迷信”,不迷信权威,不迷信书本,多实践。所以,我以前也常钻牛角,敢于置疑,这个奇异的AAA也是在这种情况下发现的。但现在,我又有了一个新观念,开始喜爱置疑自己。 所以,在看了那个网友比较靠谱的说法后,我对自己的以为然又置疑了一下。 以下为我个人对AAA指令的一点新看法。供爱好者一起来置疑,探讨,推究。 一般说: AAA指令功能:对2个未组合的BCD码相加后的结果(必须在AL中)进行调整,产生一个正确的BCD码。如果AL低4位>09H或者AF=1,则进行(AL)+06H→(AL),同时(AH)+1→(AH),AL的高4位清0,然后使AF=1,CF=1。否则,AF=0,CF=0。 标志位影响:只影响AF与CF。 我想,这个定义基本是正确的。 我也用很多数值进行了实验,基本没问题,当然前提是你遵循2个未组合的BCD码相加,至少相加的数低4位要是非压缩(非组合)BCD码,如果低4位不是,可能结果就真不正确了。 这里要探说的是AAA指令AAA执行之前,如果AL高4位为1111B(0FH),且L低4位大于9的话(如MOV AL,0f6h,ADD AL,8h,AAA),AAA就将要+6(进行BCD调整),这就导致低4位产生向高4位进位。高4位因原值为0FH,在低4位进1以后,他也产生进位,而且这个进位将被加进AH,其余将遵循指令的功能解释进行执行,此时这个进位产生1加进AH后将破坏了这个AAA指令的规则,产生AH多1的不准确值。这也正符合了那位网友所说条件不符,结果也不符。其实,如果在AAA之前,“如果AL高4位为1111B(0FH),且L低4位大于9的话,”这个条件不成立的话,即使不是非压缩BCD码进行的加法后再AAA,我们也将得到非视高4位(高4位在非组合BCD码中是不表示码值的)的正确结果。而问题正是出在这个高4位为1111B的情况下,为什么呢/因为他在低4进位后它也要进位,但假设我们转念一想,它只管进位好了,我不不这个进位加进AH里去不就好了。正是!假设这个进位不加进AH,其结果还是会正确。由此,我们可以进一步思索,在指令进行(AL)+06H→(AL)时,并不是同时(AH)+1→(AH),如果是同时(AH)+1→(AH)的话,那个AL的进位是进不了AH的,由此,我们是不是窥出,其实是(AL)+06H→(AL)后才(AH)+1→(AH)的,其实再进一步思索一下,也不是(AH)+1→(AH)的,应该是AH带进位加1,或者说是类似这样的。 如此,这个AAA指令的就很明确的呈现在我们面前,它的功能可以说是这样的: 它将先侦测AL是否大于9,AF是否=1。如果AL>9,或者AF=1,则AL+6→AL,AH带进位+1→AH,置AL高4为0,使AF=1,CF=1,否则AF=0,CF=0。 这样,理解了它的实质,我们就不必管他只能针对非组合的BCD码的调整了。可以把它拿来为我所欲用了。 为了加强它的直观性,列举几个码段,以供直观。 ;ax=0008h add al,09h ;ax=0011h (AF=1,低4位<9) aaa ;ax=0107h 符合AL低4+6,高4清0,AH+1,标准非压缩BCD调整! ;================================================= mov ax,08h ;ax=0008h add al,03h ;ax=000Bh (AF=0,低4位>9) aaa ;ax=0101h 符合AL低4+6,高4清0,AH+1,标准非压缩BCD调整! ;================================================== mov ax,02h ;ax=0002h add al,03h ;ax=0005h (AF=0,低4位<9) aaa ;ax=0005h 不必AL低4+6,高4清0,不必AH+1,标准非压缩BCD调整! ;================================================== mov ax,f2h ;ax=00f2h,虽然AL里不是标准非压缩BCD码,在非视高4位的情况下,后面也是正确结果. add al,03h ;ax=00f5h (AF=0,低4位<9) aaa ;ax=0005h 不必AL低4+6,高4清0,不必AH+1,非视高4位,结果也正确! ;==================================================== mov ax,058h ;ax=0058h,虽然AL里不是标准非压缩BCD码,在非视高4位的情况下,后面也是正确结果. add al,067h ;这里的067H也不是标准非压缩BCD码 ;ax=00bfh (AF=0,低4位>9) aaa ;ax=0105h 遵循AL低4+6,高4清0,遵循AH+1,非视高4位后,结果正确! ;======================================================= mov ax,058h ;ax=0058h,虽然AL里不是标准非压缩BCD码,在非视高4位的情况下,后面也是正确结果. add al,069h ;这里的069H也不是标准非压缩BCD码 ;ax=00c1h (AF=1,低4位<9) aaa ;ax=0107h 遵循AL低4+6,高4清0,遵循AH+1,非视高4位后,结果正确! ;========================================================= mov ax,0e8h ;ax=00e8h,虽然AL里不是标准非压缩BCD码,在非视高4位的情况下,后面也是正确结果. add al,009h ;ax=00f1h 虽然AL高4位为1111B (AF=1,低4位<9) 但非视高4结果仍正确 aaa ;ax=0107h 遵循AL低4+6,高4清0,遵循AH+1,非视高4位后,结果正确! ;==========================================================这个就是那个很奇异的结果了,但现在也不奇异了! mov ax,0f5h ;ax=00f5h,AL里不是标准非压缩BCD码 add al,006h ;ax=00fbh AL高4位为1111B (AF=0,低4位>9) 结果就要奇异了. aaa ;ax=0201h 遵循AL低4+6,高4清0,遵循AH+1,但AH=2了,它带进位加了! ;==========================================================这个是典型非标准BCD码的操作了(相加数里低4都不是BCD码),就没法保证结果的正确性了,后果自负! mov ax,000fh ;ax=000fh,AL里不是标准非压缩BCD码 add al,00fh ;Al里也不是标准非压缩BCD码 ;ax=001eh (AF=1,低4位>9) 这个结果由自己承担了.. aaa ;ax=0104h 遵循AL低4+6,高4清0,遵循AH+1,但结果真正不正确了,! 就匆匆写这点了,希望我早些时候发现的一个AAA奇异之处到现在能有个相对比较有说法的结局。 希望给有需要者一个抛引,也希望有再来者能进一步探讨。
CSDN_1AND0 2015-05-15
  • 打赏
  • 举报
回复
怎么破坏了文章的完整性了呢?
8088 汇编速查手册 一、数据传输指令 ─────────────────────────────────────── 它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据. 1. 通用数据传送指令. MOV 传送字或字节. MOVSX 先符号扩展,再传送. MOVZX 先零扩展,再传送. PUSH 把字压入堆栈. POP 把字弹出堆栈. PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈. POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈. PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈. POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈. BSWAP 交换32位寄存器里字节的顺序 XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数) CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX ) XADD 先交换再累加.( 结果在第一个操作数里 ) XLAT 字节查表转换. ── BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即 0-FFH); 返回 AL 为查表结果. ( [BX+AL]->AL ) 2. 输入输出端口传送指令. IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} ) OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 ) 输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时, 其范围是 0-65535. 3. 目的地址传送指令. LEA 装入有效地址. 例: LEA DX,string ;把偏移地址存到DX. LDS 传送目标指针,把指针内容装入DS. 例: LDS SI,string ;把段地址:偏移地址存到DS:SI. LES 传送目标指针,把指针内容装入ES. 例: LES DI,string ;把段地址:偏移地址存到ES:DI. LFS 传送目标指针,把指针内容装入FS. 例: LFS DI,string ;把段地址:偏移地址存到FS:DI. LGS 传送目标指针,把指针内容装入GS. 例: LGS DI,string ;把段地址:偏移地址存到GS:DI. LSS 传送目标指针,把指针内容装入SS. 例: LSS DI,string ;把段地址:偏移地址存到SS:DI. 4. 标志传送指令. LAHF 标志寄存器传送,把标志装入AH. SAHF 标志寄存器传送,把AH内容装入标志寄存器. PUSHF 标志入栈. POPF 标志出栈. PUSHD 32位标志入栈. POPD 32位标志出栈. 二、算术运算指令 ───────────────────────────────────────   ADD 加法. ADC 带进位加法. INC 加 1. AAA 加法的ASCII码调整. DAA 加法的十进制调整. SUB 减法. SBB 带借位减法. DEC 减 1. NEC 求反(以 0 减之). CMP 比较.(两操作数作减法,仅修改标志位,不回送结果). AAS 减法的ASCII码调整. DAS 减法的十进制调整. MUL 无符号乘法. IMUL 整数乘法. 以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算), AAM 乘法的ASCII码调整. DIV 无符号除法. IDIV 整数除法. 以上两条,结果回送: 商回送AL,余数回送AH, (字节运算); 或 商回送AX,余数回送DX, (字运算). AAD 除法的ASCII码调整. CBW 字节转换为字. (把AL中字节的符号扩展到AH中去) CWD 字转换为双字. (把AX中的字的符号扩展到DX中去) CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去) CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去) 三、逻辑运算指令 ───────────────────────────────────────   AND 与运算. OR 或运算. XOR 异或运算. NOT 取反. TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果). SHL 逻辑左移. SAL 算术左移.(=SHL) SHR 逻辑右移. SAR 算术右移.(=SHR) ROL 循环左移. ROR 循环右移. RCL 通过进位的循环左移. RCR 通过进位的循环右移. 以上八种移位指令,其移位次数可达255次. 移位一次时, 可直接用操作码. 如 SHL AX,1. 移位>1次时, 则由寄存器CL给出移位次数. 如 MOV CL,04 SHL AX,CL 四、串指令 ───────────────────────────────────────  DS:SI 源串段寄存器 :源串变址. ES:DI 目标串段寄存器:目标串变址. CX 重复次数计数器. AL/AX 扫描值. D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量. Z标志 用来控制扫描或比较操作的结束. MOVS 串传送. ( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. ) CMPS 串比较. ( CMPSB 比较字符. CMPSW 比较字. ) SCAS 串扫描. 把AL或AX的内容与目标串作比较,比较结果反映在标志位. LODS 装入串. 把源串中的元素(字或字节)逐一装入AL或AX中. ( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. ) STOS 保存串. 是LODS的逆过程. REP 当CX/ECX0时重复. REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX0时重复. REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX0时重复. REPC 当CF=1且CX/ECX0时重复. REPNC 当CF=0且CX/ECX0时重复. 五、程序转移指令 ───────────────────────────────────────  1>无条件转移指令 (长转移) JMP 无条件转移指令 CALL 过程调用 RET/RETF过程返回. 2>条件转移指令 (短转移,-128到+127的距离内) ( 当且仅当(SF XOR OF)=1时,OP1循环控制指令(短转移) LOOP CX不为零时循环. LOOPE/LOOPZ CX不为零且标志Z=1时循环. LOOPNE/LOOPNZ CX不为零且标志Z=0时循环. JCXZ CX为零时转移. JECXZ ECX为零时转移. 4>中断指令 INT 中断指令 INTO 溢出中断 IRET 中断返回 5>处理器控制指令 HLT 处理器暂停, 直到出现中断或复位信号才继续. WAIT 当芯片引线TEST为高电平时使CPU进入等待状态. ESC 转换到外处理器. LOCK 封锁总线. NOP 空操作. STC 置进位标志位. CLC 清进位标志位. CMC 进位标志取反. STD 置方向标志位. CLD 清方向标志位. STI 置中断允许位. CLI 清中断允许位. 六、伪指令 ───────────────────────────────────────   DW 定义字(2字节). PROC 定义过程. ENDP 过程结束. SEGMENT 定义段. ASSUME 建立段寄存器寻址. ENDS 段结束. END 程序结束.

21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧