Hi, guys,

I'm trying to save/restore some registers while calling the C prinf functon from the asm (I don't know a better way to write a floating point number to the console). Now, I've got this piece of code:


printf_number:
push rdi
push rax
push rsi
;push rax

mov edi, floatformat
mov eax, 1
call printf

;pop rax
pop rsi
pop rax
pop rdi
ret; printf_number


This code produces a segmentation fault. But if I uncomment the push/pop pair, everything goes fine. I noticed that it doesn't depend depend on the number of pushes/pops, just on the fact that it's odd/even. Does this have something to do with the stack alignment?
Any explanation, please?

Thanks,
Igor
Posted on 2009-08-28 00:57:09 by ideruga
Shouldn't rdi be rdx? And shouldn't the stack be 16-byte aligned?
Posted on 2009-08-28 05:07:48 by ti_mo_n

Shouldn't rdi be rdx? And shouldn't the stack be 16-byte aligned?


Well, no, rdi shouldn't be rdx: I'm using edi, so I want to save and then restore it. Why would I want to use rdx instead?

As for stack alignment, thanks for the hint! It might be the problem... Any resources/articles about it?

Thanks!
Igor
Posted on 2009-08-29 00:42:04 by ideruga
Why would I want to use rdx instead?

Uhm, because the function expects it? ;p And if it's 64-bit, it should be rcx, rdx, etc. I really don't know why are you setting eax and edi before calling printf. It this MSVCRT's printf or some custom printf function?


As for stack alignment, thanks for the hint! It might be the problem... Any resources/articles about it?

Look at links in this topic.
Posted on 2009-08-29 04:55:25 by ti_mo_n
Your segfault is caused due to printf requiring you to clean up the stack after the call because of the 'push eax'. When you put in the extra pop, you are affectively cleaning up the stack. You could have also used 'add esp, 4'.

printf_number:
push rdi
push rax
push rsi

mov edi, floatformat
mov eax, 1
call printf
add esp, 4

pop rsi
pop rax
pop rdi
ret; printf_number


Remember your stack layout, if you leave the stack unbalanced after that call then RET will pop that value off and try to return to it.
Posted on 2009-11-02 14:27:12 by Synfire
I'm not very familiar (not at all, in fact) with 64-bit code, but I doubt that "add esp, 4" is gonna work. If he had pushed a parameter to printf (which he didn't AFAICS) he'd want "add rsp, 8", no? I'm guessing the stack alignment is the problem.

While you guys are (apparently) rearranging the board, you might want to consider a separate section for 64-bit - maybe two, 'cause Windows and Linux are different. It's a "whole new ballgame", I'm starting to understand... Just a thought...

64-bit tutorial here:

http://www.vikaskumar.org/wiki/index.php?title=X86-64_Tutorial

Dunno if it's any good...

"It this MSVCRT's printf or some custom printf function?" - 'scuse me, I've gotta wipe the coffee off my monitor. :)

Best,
Frank

Posted on 2009-11-02 16:04:28 by fbkotler
Lol, I really shouldn't post in the middle of the night. XD

I didn't even notice it was 64-bit code, and from my memory I thought he was pushing EAX.

All that being the case. When you call printf you set eax to the number of floating point arguments you are passing. For example:

	mov rsi, 
mov edi, fmtFloat
mov eax, 1
call printf


This leads me to believe that you are calling the 'printf_number' like this:

	mov rsi, 
call printf_number


Given this assumption your code "should" work. The only reason it should be crashing is if you've unbalanced the stack before the call to where RET is popping off something other than the return address. Could you post more code?
Posted on 2009-11-03 09:36:15 by Synfire