0x07 Yasm: Echo with libc.
Let us write something with standard C functions like printf or scanf. What I plan to learn from this is how to link the program with libc and do a little refactor to program structure.
The mini topic for this post is 'echo'. We want to read some string and print
it. To do this with libc functions one needs to let known which functions are
external. For this purpose, we can use extern
.
I'm still using ld. This is the reason why I use _start label and have to
finish the program with syscall
instead of, for example, ret
.
But now _start function calls main. main do full stack frame and do
'echo' job.
; asm01.s - scanf version
global _start
extern printf
extern scanf
section .data
msg db "write something for echo:",0x0a,0x00
frm db "%127s\n",0x00
frm2 db "%s",0x00
emg db 0x0a,"the end...",0x0a,0x00
section .text
main:
push rbp
mov rbp, rsp
sub rsp, 0x80
lea rdi, [msg]
call printf
lea rdi, [frm]
mov rsi, rsp
call scanf
lea rdi, [frm2]
mov rsi, rsp
call printf
lea rdi, [emg]
call printf
leave
ret
_start:
call main
_exit:
mov rax, 60
mov rdi, 0
syscall
To build this I created Makefile. In yasm section -g dwarf2
is for
debug information. Linker line is also longer. It linked additional c library
(-lc
). But this was not enough. When I tried to run a program linked in
this way I've got: 'no such file or directory'. I've read somewhere that ld
has some problems with libc on some distros. The way to solve this is to link
dynamically real lib.
# Makefile
all: prog
prog: asm01.o
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -o asm01 asm01.o
asm01.o: asm01.s
yasm -f elf64 -g dwarf2 asm01.s
clean:
rm -rf asm01.o
rm -rf asm01
$ ./asm01
write something for echo:
Echo is a nice function.... print whatever you put in...
Echo
the end...
Hmmm, ok something goes wrong... Ah, yes, %s
reads string to a first white
character. Not what I intended. First I go for fgets. But it needs FILE*
structure for stdin. I didn't want to handle standard descriptions
so I have changed my mind to read. So change scanf to read.
; asm01.s
global _start
extern printf
extern scanf
extern read
section .data
msg db "write something for echo:",0x0a,0x00
frm db "%s",0x00
emg db "the end...",0x0a,0x00
section .text
main:
push rbp
mov rbp, rsp
sub rsp, 0x80
lea rdi, [msg]
call printf
mov rdi, 0
mov rsi, rsp
mov rdx, 0x80
call read
lea rdi, [frm]
mov rsi, rsp
call printf
lea rdi, [emg]
call printf
leave
ret
_start:
call main
_exit:
mov rax, 60
mov rdi, 0
syscall
Ok, this is what I want. And Makefile works like a charm...
...SQUEAK!
Comments
Comments powered by Disqus