Reputation: 2384
I am trying to convert an input character to an output symbol in x86 assembly. As an example, if the user enters A
I want the below to be output:
$
$ $
$$$$$
$ $
$ $
And for B
:
$$$$
$ $
$$$$
$ $
$$$$
etc. My current method is to set up a string of 0's and 1's and then loop through and convert a 0
to a space and a 1
to a $
. I use a b
as a line break (i.e. new line) and an x
as end of string.
My code below (just showing A
run through to shorten code):
section .data
; constants
NULL equ 0
EXIT_SUCCESS equ 0
EXIT_FAIL equ 1
SYS_exit equ 60
SYS_read equ 0
SYS_write equ 1
STD_in equ 0
STD_out equ 1
; other
text1 db "Please enter an upper-case letter from A-E: ",0
errmsg db "Error: incorrect letter chosen.",0
sucmsg db "Success.",0
symA db "00100b01010b11111b10001b10001x ",0
space db " "
dollar db "$"
lbreak db "b"
lend db "x"
section .bss
; reserve space for user input
letter resb 1
section .text
global _start
_start:
; print question
mov rax, text1
call _printText
; get user input
; sys_read (0, latter, 1)
mov rax, SYS_read
mov rdi, STD_in
mov rsi, letter
mov rdx, 1
syscall
; dereference rsi
movzx rsi, byte [letter]
; jump conditionals
mov rdx, "A"
cmp rsi, rdx
je _printA
; default jump if no match
; print fail msg
mov rax, errmsg
call _printText
jmp _exitFail
_printA:
xor eax, eax
; sys_write (1, text, 1)
mov rax, symA
call _printText
call _printChar
jmp _exitSuccess
_exitFail:
; default error exit
; sys_exit (1)
mov rax, SYS_exit
mov rdi, EXIT_FAIL
syscall
_exitSuccess:
; print success msg
mov rax, sucmsg
call _printText
; sys_exit (0)
mov rax, SYS_exit
mov rdi, EXIT_SUCCESS
syscall
; functions
_printText:
push rax
mov rbx, 0
_ptLoop:
inc rax
inc rbx
mov cl, [rax]
cmp cl, 0
jne _ptLoop
mov rax, SYS_write
mov rdi, STD_out
pop rsi
mov rdx, rbx
syscall
ret
_printChar:
;push rax
mov rbx, 0
_pcLoop:
inc rax
inc rbx
mov cl, [rax]
; if 0
cmp cl, 0
je _movSpace
; if 1
cmp cl, 1
je _movSymbol
; if newline
cmp cl, lbreak
je _movNewLine
; if end
cmp cl, lend
je _endPrint
_movSpace:
mov rcx, space
loop _pcLoop
_movSymbol:
mov rcx, dollar
loop _pcLoop
_movNewLine:
mov rcx, "\n"
loop _pcLoop
_endPrint:
mov rax, SYS_write
mov rdi, STD_out
mov rsi, rcx
mov rdx, rbx
syscall
ret
Currently, I have tried to debug as I was getting Segmentation fault (core dumped)
in the _printChar
function, however, now with the above code I am unable to create the executable file as it is returning the below error:
(.text+0x10e): relocation truncated to fit: R_X86_64_8 against '.data'
(.text+0x113): relocation truncated to fit: R_X86_64_8 against '.data'
when trying to run the below command in terminal:
ld filename.o -o filename
Can anyone suggest anything to assist with code above to achieve the objective I am after?
Upvotes: 0
Views: 311
Reputation: 5775
I assume that you make your program with
nasm -f elf64 filename.asm -o filename.o -l filename.lst
ld filename.o -o filename
Linker reports a problem at .text+0xca
, so you need to find in the "filename.lst" what instruction was generated at this offset 0xca
in the .text
section:
....
112 000000C3 80F901 cmp cl, 1
113 000000C6 7416 je _movSymbol
114 ; if newline
115 000000C8 80F9[78] cmp cl, lbreak
116 000000CB 741D je _movNewLine
117 ; if end
118 000000CD 80F9[79] cmp cl, lend
119 000000D0 741F je _endPrint
....
It's the cmp cl, lbreak
. Looking at the definition lbreak db "b"
it obvious that your instruction incorrectly tried to compare a byte-value in cl
with the offset of variable lbreak
in section .data
, which happens to be 78. You probably intended to compare cl
with the value "b"
stored in memory, using cmp cl, [lbreak]
or even better, with the immediate value: cmp cl,"b"
.
Also consider printing the big letter as one 0-terminated string, using a single _printText
:
SECTION .data
BigA DB " $ ",10
DB " $ $ ",10
DB "$$$$$",10
DB "$ $",10
DB "$ $",10
DB 0
BigB DB "$$$$ ",10
DB "$ $",10
DB "$$$$ ",10
DB "$ $",10
DB "$$$$ ",10
DB 0
Upvotes: 2