添加127或更少不能同时设置和CF(对于任何起始值)。也许你读到的是关于添加
1
? (请注意
inc
/
dec
保持CF不变,因此这仅适用于
add al, 1
)
顺便说一句,128+128是第一对设置这两个标志(对于8位操作数大小)的输入,如果从
0..255
. 我写了一个程序就是为了做到这一点。
global _start
_start:
mov al, 128
add al, 128 ; set a breakpoint here and single step this, then look at flags
xor ecx, ecx
xor edx, edx
.edx: ; do {
.ecx: ; do {
movzx eax, cl ; eax as a scratch register every iteration
; writing to eax instead of al avoids a false dependency for performance.
; mov eax, ecx is just as good on AMD and Haswell/Skylake, but would have partial-reg penalties on earlier Intel CPUs.
add al, dl
seto al ; al = OF (0 or 1)
lahf ; CF is the lowest bit of FLAGS. LAFH loads AH from the low byte of FLAGS.
test ah, al ; ZF = OF & CF
jnz .carry_and_overflow
.continue:
add cl, 1 ; add to set CF on unsigned wraparound
jnc .ecx ; } while(cl++ doesn't wrap)
; fall through when ECX=0
add dl, 1
jnc .edx ; } while(dl++ doesn't wrap)
xor edi,edi
mov eax, 231
syscall ; exit(0) Linux 64-bit.
.carry_and_overflow:
int3 ; run this code inside GDB.
; int3 is a software breakpoint
; if execution stops here, look at cl and dl
jmp .continue
使用NASM或YASM在Linux(或任何操作系统,如果您在退出系统调用之前在断点处停止)上构建。
yasm -felf64 -Worphan-labels -gdwarf2 foo.asm &&
ld -o foo foo.o
我在gdb下用
gdb ./foo
然后
run
.
在我的
~/.gdbinit
我有:
set disassembly-flavor intel
layout reg
set print static-members off
set print pretty on
macro define offsetof(t, f) &((t *) 0)->f) # https://stackoverflow.com/questions/1768620/how-do-i-show-what-fields-a-struct-has-in-gdb#comment78715348_1770422
layout reg
将GDB置于文本UI全屏模式(而不是面向行)。按住return键一段时间后
c
(继续)命令(在
rax=128
/
rdx=128
),然后点击control-L重新绘制屏幕,因为GDB的TUI功能不太好,我得到了以下结果:
âââRegister group: generalâââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
ârax 0x301 769 rbx 0x0 0 â
ârcx 0xa7 167 rdx 0x85 133 â
ârsi 0x0 0 rdi 0x0 0 â
ârbp 0x0 0x0 rsp 0x7fffffffe6c0 0x7fffffffe6c0 â
âr8 0x0 0 r9 0x0 0 â
âr10 0x0 0 r11 0x0 0 â
âr12 0x0 0 r13 0x0 0 â
âr14 0x0 0 r15 0x0 0 â
ârip 0x4000a5 0x4000a5 <_start.carry_and_overflow+1> eflags 0x202 [ IF ] â
âcs 0x33 51 ss 0x2b 43 â
âds 0x0 0 es 0x0 0 â
âfs 0x0 0 gs 0x0 0 â
â â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â0x400089 <_start.edx+5> seto al â
â0x40008c <_start.edx+8> lahf â
â0x40008d <_start.edx+9> test ah,al â
â0x40008f <_start.edx+11> jne 0x4000a4 <_start.carry_and_overflow> â
â0x400091 <_start.continue> add cl,0x1 â
â0x400094 <_start.continue+3> jae 0x400084 <_start.edx> â
â0x400096 <_start.continue+5> add dl,0x1 â
â0x400099 <_start.continue+8> jae 0x400084 <_start.edx> â
â0x40009b <_start.continue+10> xor edi,edi â
â0x40009d <_start.continue+12> mov eax,0xe7 â
â0x4000a2 <_start.continue+17> syscall â
â0x4000a4 <_start.carry_and_overflow> int3 â
>â0x4000a5 <_start.carry_and_overflow+1> jmp 0x400091 <_start.continue> â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
native process 5074 In: _start.carry_and_overflow L37 PC: 0x4000a5
Program received signal SIGTRAP, Trace/breakpoint trap.
_start.carry_and_overflow () at foo.asm:37
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
_start.carry_and_overflow () at foo.asm:37
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
_start.carry_and_overflow () at foo.asm:37
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
_start.carry_and_overflow () at foo.asm:37
(gdb)
该模式很有趣,但一旦你停下来思考数学问题,就很容易解释:对于DL=128,从128到255的所有CL值都会设置CF和OF。但对于更高的DL值,只有从128到小于255的某个值的CL同时设置这两个值。因为133代表133-256=-123,并且
(-123) + (-5) = -128
,没有签名溢出。非常大的无符号值表示有符号值为-1或略低于1。
另请参见: