【汇编】pushf popf

两个指令的作用分别是将16位标志寄存器压入栈、从栈中取出,但是貌似没人做实验验证。
这里做个实验加深理解,顺便总结下几个标志寄存器的作用。


一、结构

8086CPU的flag寄存器的结构如下:

OF:判断运算结果是否溢出
CF:判断运算过程中是否产生进位/借位
ZF:判断结果是否为0
PF:所有二进制位中1的个数是否为偶数
SF:判断结果是否为负数
DF:方向标志(控制si、di的递增,递减)

首先查看flag寄存器的初始情况。
指令:pushf
【汇编】pushf popf_第1张图片
此时flag=3202H,将其转为二进制则为:
0011 0010 0000 0010b
对比下图,可以发现目前学的6个标志位默认位为0。

二、实验

改变指令:

mov ax,1
sub ax,1
pushf

【汇编】pushf popf_第2张图片

此时flag寄存器=3246H,二进制表示为:
0011 0010 0100 0110b
第6位=1,也就是ZF=1,代表运算结果为0。
注意到第3位从原来的0变为了1,这一位是PF,PF=1代表二进制中1的个数位偶数。
继续改变指令:

mov al,127
add al,1
pushf

根据所学知识,此时8位寄存器al发生了正溢出,OF应该置为1。我们查看结果。
【汇编】pushf popf_第3张图片
flag=3A92H,其二进制表示为:
0011 1010 1001 0010b
OF处于flag中的第12位,此时OF=1。和我们的猜想一致。
注意到,这里的第8位SF置为了1,但是实际结果为正数而非负数。这是因为在溢出的情况下,逻辑上结果的正负不代表真正的结果。假设寄存器为16位寄存器ax,实际上SF应该对0080H进行判断,而非80H。
【汇编】pushf popf_第4张图片

继续改变指令:

mov al,-1
add al,-128
pushf

此时运算结果超出了8位寄存器可表示的最大范围,产生了借位,并且负溢出了,所以OF和CF应该都为1。

【汇编】pushf popf_第5张图片
flag=3A03H,其二进制表示为
0011 1010 0000 0011b
第1位的CF,第12位的OF都置为了1,与猜想结果一致。
注意到,此时SF置为了0,与实际正负不一致。若进行的是16位的运算,运算结果为FF7FH,即-1256+716+15=-129。
【汇编】pushf popf_第6张图片
flag=3283H,OF=0(未溢出),CF=1(产生借位),SF=1(最高位为负数)。

三、总结

1、pushf、popf分别将16位标志寄存器入栈、从栈中取出。
2、当OF=0,未产生溢出时,SF正确表示。
3、当OF=1,产生溢出时,SF表示的正负与实际结果相反。可推导公式:SF=SF’⊕OF。SF’为逻辑上的正负表示,SF为实际的正负表示。

你可能感兴趣的:(汇编,汇编)