title: Linux x86 NASM - Subroutine: Print a dword from EAX
body: <p>So I'm learning x86 Linux assembly with NASM syntax (<em>Oh god, not this again</em>, you're all thinking). I'm trying to make a subroutine that will simply print the value in EAX to stdout. The code runs and exits without error, but nothing prints. I can't figure out why. First of all, here is the file I'm working in:</p>
  
  <pre><code>segment .bss
      to_print:   resd 1
  
  segment .text
      global print_eax_val
  
  print_eax_val:                  ;       (top)
      push    dword ebx           ;Stack:  edx
      push    dword ecx           ;        ecx
      push    dword edx           ;        ebx
                                  ;       (bot)
  
      mov     ecx,eax             ;ecx = eax
  
      mov     [to_print],ecx      ;to_print = ecx
  
      mov     eax, 4              ;sys_write
      mov     ebx, 1              ;to stdout
      add     ecx, 47             ;add 47 for ASCII numbers
      mov     edx, 2              ;double word = 2 bytes
      int     0x80
  
      mov     eax, [to_print]     ;eax = original val
      pop     edx                 ;pop the registers back from the stack
      pop     ecx
      pop     ebx                 ;Stack: empty
  
      ret
  </code></pre>
  
  <p>This is called from my main file, which looks like this (this is probably irrelevant, unless I'm missing something drastic).</p>
  
  <pre><code>segment .data
          hello   db      "Hello world!", 0
          newline db      0xA
          len     equ $ - hello
          len2    equ $ - newline
  
  segment .text
          extern print_nl
          extern print_eax_val
          global main
  
  main:
          enter   0,0
  
          call    print_nl
  
          mov     eax, 1
  
          call    print_eax_val
  
          mov     ebx, 0          ;exit code = 0 (normal)
          mov     eax, 1          ;exit command
          int     0x80            ;ask kernel to quit
  </code></pre>
  
  <p><code>print_nl</code> is just another subroutine that defines and prints a newline. This runs successfully and prints a new line as expected.</p>
  
  <p>Does the problem have to do with the length parameter for my <code>sys_write</code> call? I'm giving it 2, which is the size of a <code>dword</code>, which is the size of both the <code>EAX</code> register and my <code>to_print</code> label, which I reserved with <code>resd 1</code>. I tried changing the length to 1, 4, 8, 16, and 32 out of desperation... Nothing worked.</p>
  
  <p><strong>EDIT:</strong> For anyone who is wondering, here is how I fixed the code: (I will put asterisks on lines that I changed):</p>
  
  <pre><code>segment .bss
      to_print:   resd 1
  
  segment .text
          global print_eax_val
  
  print_eax_val:                      ;       (top)
          push    dword ebx           ;Stack:  edx
          push    dword ecx           ;        ecx
          push    dword edx           ;        ebx
                                      ;       (bot)
  
          mov     ecx,eax             ;ecx = eax
  
          mov     [to_print],ecx        ;to_print = ecx
  
  ****    add     dword [to_print], 48
  
          mov     eax, 4              ;sys_write
          mov     ebx, 1              ;to stdout
  ****    mov     ecx, to_print
          mov     edx, 2
          int     0x80
  
  ****    sub     dword [to_print], 48
          mov     eax, [to_print]     ;eax = original val
          pop     edx                 ;pop the registers back from the stack
          pop     ecx
          pop     ebx                 ;Stack: empty
  
          ret
  </code></pre>
  
  <p>Basically, <code>ecx</code> must contain the <em>address</em> of the block you want to print, NOT the value itself. As is pointed out in the selected answer, this will <em>only</em> work if eax is in the range 0-9.</p>
  
  <p><strong>EDIT 2</strong>: So I was a little bit confused about the 2nd parameter for sys_write (the one stored in <code>edx</code>). I think it just refers to a number of bytes. So for a <code>dword</code>, as I was using, it would be proper to use 4 there, because a double word is 4 bytes, or 32 bits. I'm guessing it worked because x86 is little-endian. So in memory, the hex value of <code>to_print</code> would look like this:</p>
  
  <p><code>90 00 00 00</code></p>
  
  <p>And with a supplied length of two, sys_write gets:</p>
  
  <p><code>90 00</code></p>
  
  <p>So the value luckily doesn't get corrupted.</p>
  
  <p>I later changed the code to store <code>to_print</code> as a byte instead, using <code>resb 1</code> and accessing it using <code>byte</code> instead of <code>dword</code>... A byte is fine here, because I know I'm not going to give <code>to_print</code> a value above 9.</p>