0

Create a macro to print a digit stored in rax to the console. This macro should also have error handling to display an error messsage to the console if the value in rax is not really a digit(from 0 to 9)?

Macro, I created in separate file

    %macro digitPrinter 2

section .data

text1 db "You entered a digit",10,0
size1 equ $-text1

text2 db "Not a digit",10,0
size2 equ $-text2       


    mov rax,4
    mov rbx,1
    mov rcx, %1
    mov rdx, %2
    int 128



    mov rbx, [%1]

    cmp rbx, '9'
    jle check_more  

Not_digit:

    call textPrinter2   
    call exit


check_more:
    cmp rbx,48
    jl Not_digit
    call textPrinter1
    call exit


textPrinter1:   
    mov rax,4
    mov rbx,1
    mov rcx, text1
    mov rdx, size1
    int 128
    ret

textPrinter2:   
    mov rax,4
    mov rbx,1
    mov rcx, text2 
    mov rdx, size2
    int 128
    ret

exit :
    mov rax,1
    mov rbx,0
    int 128
    ret


%endmacro

Then I include this file in main .asm file

    %include "PrintDigit_3129.inc"

section .data


section .bss
result resb 1

section .text

global _start

_start:

    mov rax,'5'
    mov [result],rax
    digitPrinter result,1 
    

Programme execute perfectly using make utility but it gives run time error, "Segmentation fault(core dumped)" I think this may be due to issue in macro when accessing address of memory, I tried few times I can not fix this issue.

Jester
  • 56,577
  • 4
  • 81
  • 125
  • 4
    The immediate issue is that you forgot to switch back to `section .text` before emitting code hence you ended up in non-executable `.data`. – Jester Oct 19 '20 at 21:50
  • 1
    You cannot safely use the `int 0x80` system call interface from 64-bit code, certainly not for system calls like `write(2)` that take a pointer. Use the `syscall` interface instead. See https://stackoverflow.com/questions/46087730/what-happens-if-you-use-the-32-bit-int-0x80-linux-abi-in-64-bit-code – Nate Eldredge Oct 19 '20 at 23:30
  • 2
    Another problem is that as soon as you use your macro more than once, your assembler will barf on the multiply defined labels. You can use [local labels](https://sourceware.org/binutils/docs/as/Symbol-Names.html#Symbol-Names) to avoid this. Also, every invocation of the macro will emit additional copies of your strings, which wastes memory. This really seems like something that ought to be a subroutine rather than a macro. – Nate Eldredge Oct 19 '20 at 23:33
  • @NateEldredge: Or the string constants should be defined outside the macro. If you want to use the macro from multiple source files, though, you'd need some way to only get them defined once. Or arrange for merging of duplicate strings, which is something that GNU binutils `ld` can do, IIRC with a special section. (GCC uses this for string literals, to get them deduplicated across compilation units.) – Peter Cordes Oct 20 '20 at 01:47

0 Answers0