我见过人们在代码中使用来自C库的printf的例子,如下所示:
.data
.balign 4
hello: .asciz "Hello\n"
.text
.global main
.func main
main:
ldr r0, hello_msg
bl printf
mov r7, #1
swi 0
hello_msg: .word hello
.global printf
他们怎么知道r0会作为字符串arg传递给printf?我知道只要调用子程序,r0-r3就作为args传递,但我不知道哪个寄存器映射到哪个arg。示例:使用scanf时,r0是字符串格式,r1存储用户输入。我们怎么知道这个?我唯一的猜测是使用-S选项使用gcc编译我的* .s文件并查看已组装的文件...但是有更好的方法吗?
答案 0 :(得分:0)
I will try to explain what I have learned. The only Linux that I have is Raspbian Jessie (Raspberry Pi 3). There is a file /usr/include/arm-linux-gnueabihf/asm/unistd.h (other Linux should have unistd.h somewhere) that shows define for functions build into Linux [ex: #define __NR_write (__NR_SYSCALL_BASE+ 4)]. Look at Linux Man Page http://man7.org/linux/man-pages/man3/write.3p.html at the format.
ssize_t write(int fildes, const void *buf, size_t nbyte)
return in r0 [4] ( r0 , r1 , r2 )
I am kind of new at this, so I have included a program that helps me understand it. Also see http://man7.org/linux/man-pages/dir_by_project.html#man-pages for other formats.
@----------------------------------
@ asfileio.s
@
@ Raspbian Jessie assembly program using
@ SVC for file operations on Raspberry Pi 3
@
@ pi@RPi:~/Programs $ as -o asfileio.o asfileio.s
@ pi@RPi:~/Programs $ gcc -o asfileio asfileio.o
@ pi@RPi:~/Programs $ ./asfileio; echo $?; ls -l /tmp/test*
@ Hello world
@ A quick brown fox jumped over the lazy dog.
@ 0
@ -rw-r--r-- 1 pi pi 26 Jun 18 14:58 /tmp/testfile01.txt
@ -rw-r--r-- 1 pi pi 45 Jun 18 14:58 /tmp/testfile02.txt
@ pi@RPi:~/Programs $
@----------------------------------
@
@ http://man7.org/linux/man-pages/dir_by_project.html#man-pages
@
@ CREATE int creat(const char *pathname, mode_t mode);
@ Mode rwx {owner, group, other}
@ OPEN int open(const char *pathname, int flags);
@ Flags O_RDONLY, O_WRONLY, or O_RDWR
@ | O_APPEND
@ READ ssize_t read(int fd, void *buf, size_t count);
@ WRITE ssize_t write(int fd, const void *buf, size_t count);
@ CLOSE int close(int fd);
@ SYNC void sync(void);
@ EXIT void _Exit(int status);
@
@----------------------------------
.data
@ See /usr/include/arm-linux-gnueabihf/asm/unistd.h
@ See /usr/include/arm-linux-gnueabihf/bits/fcntl-linux.h
.equ create, 8
.equ Mode, 0644 @ -rw-r--r--
.equ open, 5
.equ Rd, 00
.equ Wr, 01
.equ RdWr, 02
.equ Apnd, 02000
.equ read, 3
.equ write, 4
.equ close, 6
.equ sync, 36
.equ exit, 1
.equ sfile, 187
@----------------------------------
.balign 4
Create:
.word dir_file, Mode, create
.balign 4
Open:
.word dir_file, RdWr | Apnd, open
.balign 4
Write:
.word data, after_data - data, write
.balign 4
Write2:
.word data2, after_data2 - data2, write
.balign 4
Read:
.word Buf, 80, read
.balign 4
Buf:
.space 80
@----------------------------------
data:
.asciz "Hello world\n"
after_data:
.balign 4
data2:
.asciz "A quick brown fox jumped over the lazy dog.\n"
after_data2:
.balign 4
dir_file:
.asciz "/tmp/testfile01.txt"
@----------------------------------
.text
.global main, _start
@_start: @ Uncommit if using ld as linker
main:
push {r4, r5, r7, lr}
b M_Program
S_Write: @ err 4 if error @ subroutine or function
@ System call to write to file (or stdout)
@ Write amt_wrote=(write( fd, &data, sizeof(data)))
@ r0=(r7=4( r0, r1=&data, r2=len(data)))
ldr r3, =Write @ address of parameters
S_Write2:
ldm r3, {r1, r2, r7} @ load write parameters
svc #0 @ Linux kernel writes
cmp r0, r2 @ check amt = len
movne r0, #4 @ set error code to 4
bne exit @ exit if error
mov r0, #0 @ success
mov pc, lr @ return to program
S_Create: @ err 8 if error
@ Create fd=(creat( &dir_file, -rw-r--r--))
@ r0=(r7=8 (r0=&dir_file, r1=0644 ))
ldr r3, =Create
ldm r3, {r0, r1, r7}
svc #0
mov r4, r0 @ save fd in r4
cmp r0, #3 @ err if < 3
movlt r0, #8
blt exit
mov r0, #0
mov pc, lr
S_Open: @ err 5 if error
ldr r3, =Open
ldm r3, {r0, r1, r7}
svc #0
mov r4, r0
cmp r0, #3
movlt r0, #5
blt exit
mov r0, #0
mov pc, lr
S_Close: @ err 6 if error
mov r7, #close
svc #0
cmp r0, #0
movne r0, #6
bne exit
mov pc, lr
S_Read:
ldr r3, =Read
ldm r3, {r1, r2, r7}
svc #0
mov pc, lr
M_Program:
@ S_Write call to write to stdout
mov r0, #1 @ fd=1=stdout
bl S_Write
@ Create, write and close file in /tmp
bl S_Create @ create file
mov r0, r4 @ move fd to r0
bl S_Write @ write to file
mov r0, r4 @ move fd to r0
bl S_Close @ close the file
@ Open same file for write append
bl S_Open @ open file
mov r0, r4 @ move fd to r0
bl S_Write @ write to file
mov r0, r4 @ move fd to r0
bl S_Close @ close file
@ Change variables for new file
ldr r3, =dir_file
add r3, #12
ldr r2, [r3]
eor r2, #0x30000
str r2, [r3]
@ Create new file, write and close
bl S_Create
mov r0, r4
ldr r3, =Write2
bl S_Write2
mov r0, r4
bl S_Close
@ Open file, read, write to stdout and close
bl S_Open
mov r0, r4
bl S_Read
mov r2, r0 @ r0 has amt read
mov r0, #1 @ fd = 1 = stdout
ldr r1, =Buf @ addr data just read
mov r7, #write
svc #0
mov r0, r4
bl S_Close
exit:
pop {r4, r5, r7, lr}
bx lr @ Exit if use gcc as linker
@ mov r7, #1 @ Exit if use ld as linker
@ svc #0 @ Exit if use ld as linker
The best docs that I have found on arm registers are http://caxapa.ru/thumbs/656023/IHI0042F_aapcs.pdf page 14.