使用cmp指令比较高数值时汇编程序异常的原因排查
问题描述
我期望程序先在控制台多次打印*行,再打印一行=,随后暂停并打印pause,之后重复该流程。但实际程序每次都会触发jg c3指令,导致每次sleep后直接打印pause并重复。不过将cmp word [counter], 0xF000改为cmp word [counter], 0xF时,程序可正常运行。请问这是什么原因?
汇编代码
global Start extern _GetStdHandle@4 extern _WriteFile@20 extern Sleep STD_OUTPUT_HANDLE equ -11 STD_INPUT_HANDLE equ -10 NULL equ 0 section .data counter dw 0 section .bss section .text Start: mov ebp, esp sub esp, 4 ; hStdOut = GetstdHandle ( STD_OUTPUT_HANDLE) Cont: push STD_OUTPUT_HANDLE call _GetStdHandle@4 mov ebx, eax mov word [counter],0 write: inc word [counter] push 0 lea eax, [ebp-4] push eax cmp word [counter], 0xF000 je c2 jg c3 c1: push (character_end-character) push character jmp do_write c2: push (character2_end-character2) push character2 jmp do_write c3: push (character3_end-character3) push character3 mov word [counter],0 push 0x0F;0x5FF0 call Sleep jmp do_write do_write: push ebx call _WriteFile@20 start_again: jmp write character: db '************************************************************************',0x0D,0x0A,NULL character_end: character2: db '=========================================================================',0x0D,0x0A,NULL character2_end: character3: db 'Pause',0x0D,0x0A,NULL character3_end:
问题原因
核心问题出在数据类型的符号解读上:
counter是16位的word类型,CPU对它的比较会遵循带符号整数规则。0xF000作为16位带符号数,对应的十进制是-4096,是负数。而你的counter从0开始自增,每次都是正整数,任何正整数都比负数大,所以第一次执行cmp后,jg(带符号大于跳转)的条件直接满足,直接跳去执行c3的暂停和打印pause逻辑。- 当你把比较值改成
0xF(十进制15)时,这是一个正的16位整数,counter从1自增到15时都满足小于等于的条件,正常走c1打印*;等于15时跳转到c2打印=;下一次自增到16,16>15触发jg c3,逻辑就符合预期了。
内容的提问来源于stack exchange,提问作者VCD_WL
相关产品推荐
相关产品推荐

