0

I am writing an x86 program to print, one line at a time: 9, 8, 7, ..., 1, 0. It compiles, and the value of count is getting decremented (I checked on the gdb debugger). But when I run the program on the command line with ./myprogram, I see no output.

This is the code:

; ------------------------------------------------------------------------------

; ------------------------------------------------------------------------------
        global    _start
; ------------------------------------------------------------------------------

; ------------------------------------------------------------------------------
        section   .text     ; Start of our code

_start:
    mov byte [count], 9
decr_loop:
    ;; Print current count value
    mov rax, 4      ; The system call for write
    mov rdi, 1      ; File descriptor/ handle for stdout (console)
    mov rsi, count      ; Address for count variable
    mov rdx, 1      ; Number of bytes to write
    syscall         ; Call Linux kernel. Trigger the write

    ;; Print newline character
    mov rax, 4      ; The system call for write
    mov rdi, 1      ; Console
    mov rsi, newline        ; Address for newline variable
    mov rdx, 1              ; Number of bytes to write
    syscall         ; Call Linux kernel. Trigger the write

    ;; Decrease the count
    dec byte [count]

    ;; Compare count to zero. Jump if greater
    cmp byte [count], 0
    jg decr_loop

    ;; This code ends the program.
        mov       rax, 60                 ; system call for exit
        xor       rdi, rdi                ; exit code 0
        syscall                           ; invoke operating system to exit
; ------------------------------------------------------------------------------

    
; ------------------------------------------------------------------------------
        section   .data
newline:
    db 10                 ; The integer 10 is a newline char
count:
    db 9              ; init count as 9, dummy variable
; ------------------------------------------------------------------------------

  • 1
    The write system call expects a buffer with text contents, not numeric. – ecm Feb 10 '23 at 08:53
  • how do i do that, please? how do i transform the integers to text? – Osasikemwen Ogieva Feb 10 '23 at 08:55
  • https://duckduckgo.com/?q=site%3Astackoverflow.com+format+number+assembly+x86-64+linux – ecm Feb 10 '23 at 08:56
  • @ecm: `mov rsi, count` does put the address in a register. The characters being printed are ASCII codes 9 through 0, all control characters. The OP claims to see no output, but on a normal terminal it should show 10 blank lines, one of them containing a tab. And also ding the terminal bell with a BEL character. – Peter Cordes Feb 10 '23 at 09:13
  • 1
    @ecm: oh, `strace ./bell` shows the other bug: 10 repeats of `stat(0x1, 0x402001) = -1 EFAULT (Bad address)`, indicating that they're using the wrong call number: they're using `__NR_write` = 4 from `unistd_32.h`, which is correct for the `int 0x80` 32-bit ABI, rather than `__NR_write` = 1 from `unistd_64.h` for the 64-bit `syscall` ABI. – Peter Cordes Feb 10 '23 at 09:16
  • 1
    Not quite a duplicate of [In Linux x86\_64 are syscalls and int 0x80 related?](https://stackoverflow.com/a/29440362) - the question isn't focused enough on call *numbers*, that's just something one answer mentions. [Linux, system call table, 32 and x64](https://stackoverflow.com/q/7764842) should work for that part of the question. – Peter Cordes Feb 10 '23 at 09:28
  • 1
    Also [new to assembly, intended to print '0' to '9' , unexpected bugs](https://stackoverflow.com/q/64376250) is an x86-64 0..9 single-digit print loop. – Peter Cordes Feb 10 '23 at 09:33
  • @PeterCordes "does put the address in a register" Yes, I should rather have written "expects a buffer with text contents, not numeric **contents**". It is correct that the original attempt passed a buffer, it was just a numeric variable rather than text variable at the position occupied by the buffer. Also good catch on the wrong system call numbers. – ecm Feb 10 '23 at 10:07
  • 1
    @ecm: Oh, I think I skimmed too quickly and misread your comment. My first assumption was that it was the common bug of passing a value not a pointer, so I was primed to misread your comment as saying that. xD. "text not numeric" is clear enough, my bad. As for trying it, I didn't notice from the code, I was just curious how it managed to not print 10 newlines so I copy/pasted it. I have a shell script `asm-link` that runs `nasm` and `ld` (and optionally objdump) so it takes about 10 secs to copy/paste, `cat > bell.asm` etc. once I've decided code isn't malicious and I'm willing to run it – Peter Cordes Feb 10 '23 at 10:16
  • Most of your issues seem to be misunderstanding unix-type system calls. You don't have to work in assembly to figure these out: probably be better off getting those working in C then take to assembly as is. – Erik Eidt Feb 10 '23 at 16:16

0 Answers0