0

Im using x86-64 NASM on WSL Ubuntu.

I'm trying to use push/pop for function params, but for some reason it makes my program return " ".

section .text
        global _start
_start:
mov edx, len  
mov ecx, msg
push ecx
push edx
call println
mov eax, 1
int 0x80

println:
pop edx
pop ecx
mov ebx, 1     
mov eax, 4   
int 0x80        
ret

section .data

msg db "Hello world!",0xa
len equ $ - msg

this returns:


Command terminated by signal 11

Not too sure what's causing this. Does anyone know? I would like to add that removing both the pushes and both the pops makes the program run perfectly fine again.

Amukh1
  • 9
  • 1
  • 1
    Your code is 32 bit code, yet you state you are programming for 64 bit mode. Which one of the two is it now? – fuz Aug 12 '22 at 17:15
  • 2
    As for your error: recall that `call` pushes the return address on the stack. So when you `pop edx` in `println`, you end up popping the return address, not the argument you pushed. To fix this, either pass the arguments in registers or load them from the stack using something like `mov edx, [esp+4]`. – fuz Aug 12 '22 at 17:16
  • 2
    loading a 32-bit address like this `mov ecx, msg` is definitely wrong in 64-bit mode. And [`int 0x80` is also wrong](https://stackoverflow.com/q/46087730/995714). In WSL you can't even use it and in WSL2 you'll need to install the 32-bit subsystem – phuclv Aug 12 '22 at 17:22
  • As @phuclv points out, you're loading the contents of the message (the first 4 bytes, or 8 bytes in 64-bit mode). You want the to load the address of `msg` instead. – Jim Mischel Aug 12 '22 at 19:23
  • 2
    @Jim, in nasm, `mov ecx, msg` loads the address, not the contents. The problem is that in 64-bit mode, the address may not fit in 32 bits. – prl Aug 12 '22 at 20:37
  • @prl oh, right. To load the contents it would be `mov ecx,[msg]`. My asm is beyond rusty. – Jim Mischel Aug 12 '22 at 20:40
  • 1
    @Jim, in some x86 assemblers, it does work the way you remembered. – prl Aug 12 '22 at 20:42
  • @phuclv: Linux non-PIE executables have symbol addresses in the low 2GiB of virtual address space, so it's not wrong to put addresses into registers with `mov r32, imm32` in 64-bit code. In fact that's optimal, and what compilers do if you use `-fno-pie`. ([How to load address of function or label into register](https://stackoverflow.com/q/57212012)). That will also make `int 0x80` happen to work in a 64-bit executable. Of course, 32-bit `push ecx` is not encodeable in 64-bit mode, so this could only have been assembled with `nasm -felf32`. – Peter Cordes Aug 12 '22 at 20:56

0 Answers0