0

Previous version of this question (that question originally had a different problem, even though the code there is now the same as the code in this question)


I am trying to make code to display a number on console in Linux 64 bit NASM, without the use of c/c++ functions (pure assembly). The code compiles and links fine but it will not give output...

It displays just newline for some time and then displays '7' forever. I am new to Assembly so I don't know what is wrong. Please help... Here is the code:

section .data
    num:        dq      102 ;my default number to get the reverse of (for now)
    nl:         db      0x0a
    nlsize:     equ     $-nl
    ten:        dq      10

section .bss
    rem:        resq        1
    remsize:    equ     $-rem

section .text
    global _start

_start:

    cmp qword [num], 0
        jng _exit       ;jump to _exit if num is not greater than 0
    mov rax, [num]      ;move the number to rax
    mov rbx, [num]      ;move the number to rbx as well so that i have original number in register to subtract and get the remainder
    mov rcx, [ten]      ;move 10 to rcx to be the divisor
    div rcx             ;divide number in rax by 10
    mov [num], rax      ;get the quotient to get the remaining number for quotient
    mul rcx             ;multiply number in rax by 10
    sub rbx, rax        ;subtract rbx - rax and store the value in rax (right?)
    mov [rem], rbx      ;get the remainder from rax. this must be done right after div (WHY??????????)
    call _disprem       ;call _disprem to display the remainder... call returns the flow back to the caller right?
    jmp _start          ;get to the loop again

_exit:
    mov rax, 60
    mov rdi, 0
    syscall

_newl:
    mov rax, 1
    mov rdi, 1
    mov rsi, nl
    mov rdx, nlsize
    syscall
    ret

_disprem:
    mov rax, 1
    mov rdi, 1
    add qword [rem], 0x0000000000000030 ;since the rem variable is quadword (64 bit)
    mov rsi, rem    ;for getting ascii value (48 is ascii 0 in decimal) to convert the rem to character
    mov rdx, remsize
    syscall
    sub qword[rem], 0x0000000000000030 ;get me my original number back plz thanks
    call _newl
    ret
Community
  • 1
  • 1
Electrux
  • 19
  • 6
  • 3
    `div rcx` requires `rdx` to be zeroed. Also it produces the remainder for you, no need to multiply and subtract. Furthermore, you will want to print 1 byte, not 8. PS: learn to use a debugger and the instruction set reference. – Jester Jun 07 '16 at 10:34
  • oh... well I thought I would use 8 bytes because it is a qword? But thanks for the information. And yea, I am learning to use gdb. – Electrux Jun 07 '16 at 11:02
  • 1
    You don't need to load `[ten]` from memory. Just do `mov ecx, 10` like a normal person. Or `div qword [ten]` if you really want to have it in memory. – Peter Cordes Jun 07 '16 at 18:11
  • Anyway, from the FAQ section of the [x86 tag wiki](http://stackoverflow.com/tags/x86/info): idiv / div problems: Zero edx first, or sign-extend eax into it. – Peter Cordes Jun 07 '16 at 18:12
  • Wow! Just adding the code to set rdx to zero did it! My code works!!! Thanks all. I set rdx to zero just above the div command. I also removed 'ten' variable and set rcx to 10 directly. Does not need qword for that. Thanks a lot guys. – Electrux Jun 08 '16 at 03:00
  • If I may, does it implicitly convert qword to byte? If I didn't need to set 10 to qword, did it implicitly take it to be a qword because of my 64 bit architecture? – Electrux Jun 08 '16 at 03:08
  • @Electrux: not sure what you are asking about, but when one part of instruction is register, like `mov rcx,10`, then from the size of register (`rcx`=64b) the ASM will deduct correct size of immediate constant, and it will search for appropriate instruction opcode to encode such constant (for programmer it doesn't matter, whether it's 8 or 64b in opcode, but he knows the whole rcx is initialized by the mov, and result is 10). The same goes for instructions like `mov [memory],eax` = 32b specified by `eax`. But with `mov [ds:di],116` you have to specific, so add like `word [ds:di]` to have 16b. – Ped7g Jun 08 '16 at 15:27
  • Ah ok that's what I was asking about. Thanks. – Electrux Jun 08 '16 at 16:18
  • [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) has a good sample implementation. – Peter Cordes Dec 21 '20 at 23:34

0 Answers0