6

I am trying to print a single digit integer in nasm assembly on linux. What I currently have compiles fine, but nothing is being written to the screen. Can anyone explain to me what I am doing wrong here?

section .text
    global _start

_start:
    mov ecx, 1          ; stores 1 in rcx
    add edx, ecx        ; stores ecx in edx
    add edx, 30h        ; gets the ascii value in edx
    mov ecx, edx        ; ascii value is now in ecx
    jmp write           ; jumps to write


write:
    mov eax, ecx        ; moves ecx to eax for writing
    mov eax, 4          ; sys call for write
    mov ebx, 1          ; stdout

    int 80h             ; call kernel
    mov eax,1           ; system exit
    mov ebx,0           ; exit 0
    int 80h             ; call the kernel again 
finfet
  • 226
  • 3
  • 5
  • 13
  • You are assigning eax to ecx, and then 4. It's probably there. – Josh Aug 01 '11 at 19:38
  • possible duplicate of [How to print a number in assembly NASM?](http://stackoverflow.com/questions/8194141/how-to-print-a-number-in-assembly-nasm) Related: http://stackoverflow.com/questions/4117422/more-efficient-way-to-output-an-integer-in-pure-assembly – Ciro Santilli OurBigBook.com Sep 29 '15 at 21:00
  • Also [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) for the general case of multi-digit numbers; `add reg, '0'` only works for numbers from 0..9 – Peter Cordes May 08 '22 at 06:07

3 Answers3

7

After reviewing the other two answers this is what I finally came up with.

sys_exit        equ     1
sys_write       equ     4
stdout          equ     1

section .bss
    outputBuffer    resb    4       

section .text
    global _start

_start:
    mov  ecx, 1                 ; Number 1
    add  ecx, 0x30              ; Add 30 hex for ascii
    mov  [outputBuffer], ecx    ; Save number in buffer
    mov  ecx, outputBuffer      ; Store address of outputBuffer in ecx

    mov  eax, sys_write         ; sys_write
    mov  ebx, stdout            ; to STDOUT
    mov  edx, 1                 ; length = one byte
    int  0x80                   ; Call the kernel

    mov eax, sys_exit           ; system exit
    mov ebx, 0                  ; exit 0
    int 0x80                    ; call the kernel again
Dave Albert
  • 1,429
  • 15
  • 21
7

This is adding, not storing:

add edx, ecx        ; stores ecx in edx

This copies ecx to eax and then overwrites it with 4:

mov eax, ecx        ; moves ecx to eax for writing
mov eax, 4          ; sys call for write

EDIT:

For a 'write' system call:

eax = 4
ebx = file descriptor (1 = screen)
ecx = address of string
edx = length of string
MRAB
  • 20,356
  • 6
  • 40
  • 33
  • I tried this, and it also compiles fine, but nothing is being written to the screen. – finfet Aug 01 '11 at 19:59
  • 1
    I still can't get it working, but I will make this the accepted answer. – finfet Aug 01 '11 at 20:36
  • @FrozenWasteland - The remaining problem is mentioned in this answer, but without calling your attention specifically to it: "ecx = address of string edx = length of string" but you have been trying to provide the data byte itself inc ecx rather than the address there and a length in edx. – Chris Stratton Aug 02 '11 at 16:12
2

From man 2 write

ssize_t write(int fd, const void *buf, size_t count);

In addition to the other errors that have been pointed out, write() takes a pointer to the data and a length, not an actual byte itself in a register as you are trying to provide.

So you will have to store your data from a register to memory and use that address (or if it's constant as it currently is, don't load the data into a register but load its address instead).

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117