2

I know printf returns the number of characters printed in EAX. Why is printf changing register ECX to 0? My code snippet:

push eax    
push intFormat
call printf 
add esp,8

I'm running my code on a 64-bit Linux distribution.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
neileap
  • 63
  • 3
  • What is the ABI for your platform? – EOF Apr 26 '16 at 21:29
  • If you are on Linux writing 32-bit code then _EAX_, _ECX_ and _EDX_ are potentially clobbered by functions you call. They need to be preserved by the caller (you) if they are needed after the call. See the [CDECL calling convention](https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl). If you are on another platform (Windows, OSX, other) let us know. If you are on Linux let us know. – Michael Petch Apr 26 '16 at 21:39
  • I am using nasm in linux64 – neileap Apr 26 '16 at 21:49
  • So you are writing 32-bit Linux applications and running them on 64-bit Linux, correct? – Michael Petch Apr 26 '16 at 21:50
  • 1
    As it stands _EAX_ will have the return value from `printf` as you know, but functions that follow the CDECL calling convention (the _C_ library included) can also clobber _ECX_, and _EDX_. They may not change, but they might and their values can't be relied upon for anything. You'll have to use different registers that don't get clobbered (EBX is available if not using PIC code, ESI, EDI are also available) or you'll have to manually preserve those registers and restore them after `printf` – Michael Petch Apr 26 '16 at 21:54
  • Since you are running on Linux, if your version of _GCC_ >= 4.5 then you should also be aligning the stack to a 16-byte boundary before making a call to the _C_ library. your code may run as expected if you don't (but it isn't guaranteed), but if you start dealing with floating point values you may find `printf` will segfault. If you don't do the alignment you may get unexpected behaviour. – Michael Petch Apr 26 '16 at 22:00
  • 1
    Have a look at the [x86 tag wiki's FAQ section](http://stackoverflow.com/tags/x86/info). I just added a calling convention entry to the FAQ section. That will lead you to the details you need to know. (@MichaelPetch: ideally those FAQ entries would include links to SO questions that make good duplicate targets. If you know any good questions to add, please do so, or drop me a note in chat and I'll take care of the formatting. I feel like there are too many links to my own questions and answers in the tag wiki. I know I could search myself, and I will eventually...) – Peter Cordes Apr 26 '16 at 22:23
  • @PeterCordes : I noticed in the x86 tag that you reference the old System V i386 ABI but I don't see a link to the revised one (I may have missed it). I'd suggest having a link to the revised one as well. A copy is kept [here](https://uclibc.org/docs/psABI-i386.pdf). The newer document (v1.0) was revised for things like the new 16-byte stack alignment (that GCC >= 4.5 uses as a default) among other things. – Michael Petch Apr 26 '16 at 22:35
  • @MichaelPetch: Thanks, I don't think I ever checked SCO's version was still current. HJ Lu's github wiki page links to the current versions of all 3 (32, x32, 64), but having the main link for it be a current version would be best. I'll take a look soon. – Peter Cordes Apr 26 '16 at 23:50
  • The Intel Open Source website 01.org maintains a copy as well at [this location](https://01.org/sites/default/files/file_attach/intel386-psabi-1.0.pdf) – Michael Petch Apr 27 '16 at 00:22

1 Answers1

3

As it stands EAX will have the return value from printf as you know, but functions that follow the CDECL calling convention (the C library included) can also clobber ECX, and EDX. They may not change, but they might and their values can't be relied upon for anything. You'll have to use different registers that don't get clobbered (EBX is available if not using PIC code, ESI, EDI are also available) or you'll have to manually preserve those registers and restore them after printf – Michael Petch

For more info on calling conventions / ABIs, see the tag wiki. There's even an FAQ section with an entry covering this question.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Armali
  • 18,255
  • 14
  • 57
  • 171