0

I have this little program written in x64 assembly:

xor    rdx,rdx
push   rdx            ;null terminator
push   0x41414141     ;AAAA
push   0x45454545     ;EEEE
mov    rsi,rsp        ;pointer to the string
mov    rdi,1          ;output file: stdout
mov    rdx,8          ;buffer size 8
mov    rax,1          ;write syscall
syscall

As you can see, I push eight bytes to the stack and when I call write with buffer size 8, I am expecting to see EEEEAAAA but the output is EEEE. However, when I set the buffer size rdx to 12, I can see the full string EEEEAAAA. What is between those four-byte blocks? Aren't they ought to be adjacent?

sikerbela
  • 388
  • 1
  • 4
  • 17
  • Check this one -- you can't push 32-bit constants or registers in x64 mode -- only 16-bit and 64-bit operand sizes are supported. http://stackoverflow.com/questions/13351363/push-on-64bit-intel-osx – Aki Suihkonen Apr 28 '15 at 11:08

1 Answers1

2

Each push writes 8 bytes, since that is the stack size in 64 bit mode. The immediate in the instruction is sign extended to 64 bits, see the instruction set reference: If the source operand is an immediate of size less than the operand size, a sign-extended value is pushed on the stack.

As such, your stack looks like (from rsp upwards):

0x0000000045454545 ; EEEE sign extended to 64 bits
0x0000000041414141 ; AAAA sign extended to 64 bits
0x0000000000000000 ; NULL terminator

As workaround you can do:

xor rdx, rdx
push rdx
mov rax, 0x4141414145454545
push rax
mov    rsi,rsp        ;pointer to the string
mov    rdi,1          ;output file: stdout
mov    rdx,8          ;buffer size 8
mov    rax,1          ;write syscall
syscall
Jester
  • 56,577
  • 4
  • 81
  • 125
  • Pushing the string as 2 byte blocks also works, as @Aki Suihkonen said. – sikerbela Apr 28 '15 at 11:15
  • Pushing 2 byte blocks is inefficient and also temporarily messes up stack alignment which might be an issue under some circumstances. – Jester Apr 28 '15 at 11:18