Discussion:
pusha and popa changes to sp register
(too old to reply)
bilsch01
2021-01-21 07:23:48 UTC
Permalink
I read the x86 instruction reference. It is clear to me that pusha
will decrement sp by 16. But it sounds like popa will increment sp by
only 14. Is that correct?

The text of the reference for popa says:

Pops doublewords (POPAD) or words (POPA) from the stack into the
general-purpose registers. The registers are loaded in the following
order: EDI, ESI, EBP, EBX, EDX, ECX, and EAX (if the operand-size
attribute is 32) and DI, SI, BP, BX, DX, CX, and AX (if the operand-size
attribute is 16). (These instructions reverse the operation of the
PUSHA/PUSHAD instructions.) The value on the stack for the ESP or SP
register is ignored. Instead, the ESP or SP register is incremented
after each register is loaded.
Kerr-Mudd,John
2021-01-21 10:04:56 UTC
Permalink
Post by bilsch01
I read the x86 instruction reference. It is clear to me that pusha
will decrement sp by 16. But it sounds like popa will increment sp by
only 14. Is that correct?
Hardly likely is it? It would break a lot of things; after 'popa' SP is
set to the pre 'pusha' value; even though a value for SP is put on the
stack by 'pusha', it's ignored on restore.
Post by bilsch01
Pops doublewords (POPAD) or words (POPA) from the stack into the
general-purpose registers. The registers are loaded in the following
order: EDI, ESI, EBP, EBX, EDX, ECX, and EAX (if the operand-size
attribute is 32) and DI, SI, BP, BX, DX, CX, and AX (if the operand-
size
Post by bilsch01
attribute is 16). (These instructions reverse the operation of the
PUSHA/PUSHAD instructions.) The value on the stack for the ESP or SP
register is ignored. Instead, the ESP or SP register is incremented
after each register is loaded.
(this is internal, you don't get to see the value of SP until pusha/pop
has completed)
--
Bah, and indeed, Humbug.
wolfgang kern
2021-01-21 10:37:08 UTC
Permalink
Post by bilsch01
I read the x86 instruction reference. It is clear to me that pusha
will decrement sp by 16. But it sounds like popa will increment sp by
only 14. Is that correct?
Pops doublewords (POPAD) or words (POPA) from the stack into the
general-purpose registers. The registers are loaded in the following
order: EDI, ESI, EBP, EBX, EDX, ECX, and EAX (if the operand-size
attribute is 32) and DI, SI, BP, BX, DX, CX, and AX (if the operand-size
attribute is 16). (These instructions reverse the operation of the
PUSHA/PUSHAD instructions.) The value on the stack for the ESP or SP
register is ignored.
Instead, the ESP or SP register is incremented
after each register is loaded.
this last sentence is just nonsense, both PUSHA(d) and POPA(d)
add/sub 16(32) bytes after all moves done.
But POPA wont alter (e)SP, coz this wouldn't make any sense.

So this two instructions pair just fine :)
__
wolfgang
Rod Pemberton
2021-01-21 22:26:29 UTC
Permalink
On Wed, 20 Jan 2021 23:23:48 -0800
Post by bilsch01
I read the x86 instruction reference. It is clear to me that pusha
will decrement sp by 16. But it sounds like popa will increment sp by
only 14. Is that correct?
Pops doublewords (POPAD) or words (POPA) from the stack into the
general-purpose registers. The registers are loaded in the following
order: EDI, ESI, EBP, EBX, EDX, ECX, and EAX (if the operand-size
attribute is 32) and DI, SI, BP, BX, DX, CX, and AX (if the
operand-size attribute is 16). (These instructions reverse the
operation of the PUSHA/PUSHAD instructions.) The value on the stack
for the ESP or SP register is ignored. Instead, the ESP or SP
register is incremented after each register is loaded.
They just didn't mention ESP/SP:
https://www.sandpile.org/x86/sframe.htm


Sandpile.org
https://www.sandpile.org
"The world's leading source for technical x86 processor information"

--
bilsch01
2021-01-25 01:11:11 UTC
Permalink
Post by bilsch01
I read the x86 instruction reference. It is clear to me that pusha
will decrement sp by 16. But it sounds like popa will increment sp by
only 14. Is that correct?
Pops doublewords (POPAD) or words (POPA) from the stack into the
general-purpose registers. The registers are loaded in the following
order: EDI, ESI, EBP, EBX, EDX, ECX, and EAX (if the operand-size
attribute is 32) and DI, SI, BP, BX, DX, CX, and AX (if the operand-size
attribute is 16). (These instructions reverse the operation of the
PUSHA/PUSHAD instructions.) The value on the stack for the ESP or SP
register is ignored. Instead, the ESP or SP register is incremented
after each register is loaded.
I rearranged the beginning of the program (MSDOS 5.0 FAT16 boot sector)
and entered values of sp register to the left of the instructions that
cause a change. It is a useful tool to determine some values (on paper)
as the program proceeds. I wonder if what I have following the popa
instructions is a good guess, or does anybody have a better suggestion?

TIA. Bill S.

00000000 xor ax,ax
00000002 mov ds,ax
00000004 mov ss,ax
00000006 7c00 mov sp,0x7c00
00000009 mov bp,sp
0000000B cld
0000000C sti
0000000D mov [bp+0x24],dl
00000010 mov al,[bp+0x10]
00000013 mul word [bp+0x16]
00000016 add ax,[bp+0xe]
00000019 adc dl,dh
0000001B add ax,[bp+0x1c]
0000001E adc dx,[bp+0x1e]
00000021 7bfe push byte +0x54
00000023 7c00 pop es
00000024 7bfe push ds
00000025 mov bx,0x53a
00000028 mov si,0x7e00
0000002B mov cx,[bp+0x11]
0000002E 7bfc push es
0000002F 7bfa call 0x11d

0000011D 7bea pusha

[ax ]--> 7bf8
[cx ]--> 7bf6
[dx ]--> 7bf4
[bx ]--> 7bf2 0x53a
[spi]--> 7bf0
[bp ]--> 7bee 0x7c00
[si ]--> 7bec 0x7e00
[di ]--> 7bea

0000011E 7be8 push es
0000011F 7be6 push ss
00000120 7be4 push ss
00000121 7be2 push dx
00000122 7be0 push ax
00000123 7bde push es
00000124 7bdc push ss
00000125 7bda push byte +0x1
00000127 7bd8 push byte +0x10
00000129 mov si,sp
0000012B mov dl,[bp+0x24]
0000012E 7bd6 push dx
0000012F 7bd4 push dx
00000130 7bd2 push dx
00000131 mov ah,0x8
00000133 int 0x13
00000135 les bx,[si+0x4]
00000138 jc 0xf9
0000013A and cx,byte +0x3f
0000013D mov [bp+0x18],cx
00000140 movzx ax,dh
00000143 inc ax
00000144 mov [bp+0x1a],ax
00000147 mul cx
00000149 xchg ax,di
0000014A mov ax,[si+0x8]
0000014D mov dx,[si+0xa]
00000150 jz 0x16c
00000152 cmp dx,di
00000154 jnc 0x16c
00000156 div di
00000158 xchg ax,dx
00000159 div cl
0000015B mov cl,0x2
0000015D xchg ch,dl
0000015F shr dx,cl
00000161 xchg ah,cl
00000163 inc cx
00000164 or cl,dl
00000166 xchg dh,al
00000168 or al,al
0000016A jz 0x174
0000016C mov ah,0x42
0000016E 7bd0 push ss
0000016F 7bd2 pop es [es]=0
00000170 mov byte [bp+0x2],0xe
00000174 inc ax
00000175 mov dl,[bp+0x24]
00000178 int 0x13
0000017A jc 0x138
0000017C 7be8 lea sp,[si+0x10]
0000017F add word [si+0x10],byte +0x20
00000183 7bea pop es
00000184 7bfa popa

[7bec]--> di
[7bee]--> si
[7bf0]--> bp
[7bf2]-->
[7bf4]--> bx
[7bf6]--> dx
[fbf8]--> cx
[7bfa]--> ax

00000185 inc ax
00000186 jnc 0x189
00000188 inc dx
00000189 7bfc ret

00000032 7bfe pop es [es]=0x54
00000033 mov di,0x200
00000036 sub di,byte +0x20
00000039 jc 0x2e
0000003B 7bfc push si
0000003C lea si,[si-0x10]
0000003F cmp [si+0xf],bh
00000042 jc 0x65
00000044 7bec pusha

[ax ]--> 7bfa
[cx ]--> 7bf8
[dx ]--> 7bf6
[bx ]--> 7bf4
[spi]--> 7bf2
[bp ]--> 7bf0
[si ]--> 7bee
[di ]--> 7bec

00000045 ja 0x51
00000047 mov al,[0x417]
0000004A and al,0xf
0000004C cmp al,[si+0xe]
0000004F jnz 0x56
00000051 mov cx,0xb
00000054 repe cmpsb
00000056 7bfc popa

[7bee]--> di
[7bf0]--> si
[7bf2]--> bp
[7bf4]-->
[7bf6]--> bx
[7bf8]--> dx
[7bfa]--> cx
[7bfc]--> ax

00000057 jnz 0x3c
00000059 7bf8 push word [bx+di+0x20]
0000005C cmp [si+0xc],bx
0000005F jnz 0x3b
00000061 7bfa pop word [bx]
00000063 jmp short 0x3c
00000065 7bfc pop si
00000066 loop 0x36

00000068 7bfe pop di
00000069 mov sp,bp
0000006B mov [bx-0x20],di
0000006E 7bfc push dx
0000006F 7bfa push ax
00000070 les bx,[si+0xa]
00000073 xchg bh,cl
00000075 7bf8 push es
00000076 7bf6 push di
00000077 mov bl,[bp+0xd]
0000007A lea ax,[di-0x2]
0000007D mul bx
0000007F add ax,[bp-0x4]
00000082 adc dx,[bp-0x2]
00000085 or di,di
00000087 jz 0x102
00000089 7bf8 call 0x11d
0000008C dec bx
0000008D loopne 0x89

Loading...