【问题标题】:Using C functions with ARM assembly将 C 函数与 ARM 程序集结合使用
【发布时间】:2016-07-11 16:03:04
【问题描述】:

我已经看到人们在他们的代码中使用 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 文件并查看组装文件......但是有更好的方法吗?

【问题讨论】:

  • 是的,您阅读了 C 库使用的 ABI...
  • 我已经看过ABI for ARM,它没有提到任何关于寄​​存器的内容。此外,它是我能找到的唯一 C 库 ABI。我在哪里可以找到指定如何使用每个寄存器的 ABI?
  • 它是 eabi 或 arm 的一部分。也许你没有找对一个/地方。归根结底,编译器是正确的,如果没有其他事情与自己对话,那么生成一个简单的 C 函数,从另一个简单的 C 函数调用它,并且对于该编译器,它选择的寄存器是正确的。现在,当您开始执行 64 位变量或浮点等操作时,寄存器/堆栈的使用可能会变得非线性(例如,它们可能会跳过 r1 或 r3)。只需重新制作原型并模仿即可。
  • 据我所知,对于 arm 来说,r0 是第一个参数 r1 第二个等等(再次在一个通用寄存器中使用正常的小尺寸),然后在 r3 之后它转到堆栈。如此有趣(a,b,c,d),如果这些都是 32 位、16 或 8 位按值传递,那么 r0 = a,r1=b,依此类推。如果您将 b 设为 64 位整数,尽管它可能会跳过 r1 并将 r2/r3 用于 b 然后 C 和 D 在堆栈中。但是您必须尝试一下才能找到答案。
  • 不知道脚本快速模型与任何事情有什么关系,但 ARM EABI 的相关部分(假设您不在某些古老或深奥的系统上)将是 Procedure Call Standard,即绝对是关于寄存器(与数据类型无关)。请注意,EABI 具有特定于平台的方面,但假设您在 Linux 上,在这个级别上不必担心 GNU 变体的具体细节可能是安全的(我什至不确定我是否知道它们,除了 r9没有特殊用途)。

标签: assembly arm calling-convention


【解决方案1】:

我将尝试解释我所学到的。我唯一拥有的 Linux 是 Raspbian Jessie (Raspberry Pi 3)。有一个文件 /usr/include/arm-linux-gnueabihf/asm/unistd.h (其他 Linux 应该有 unistd.h 某处)显示为 Linux 内置函数的定义 [例如:#define __NR_write (__NR_SYSCALL_BASE+ 4)]。查看 Linux 手册页 http://man7.org/linux/man-pages/man3/write.3p.html 的格式。

     ssize_t write(int fildes, const void *buf, size_t nbyte)
return in r0  [4] (      r0  ,            r1  ,       r2    )

我对此有点陌生,所以我提供了一个帮助我理解它的程序。另请参阅http://man7.org/linux/man-pages/dir_by_project.html#man-pages 了解其他格式。

@----------------------------------
@ 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

我在 arm 寄存器上找到的最佳文档是 http://caxapa.ru/thumbs/656023/IHI0042F_aapcs.pdf 第 14 页。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-31
    • 2012-05-31
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 2011-06-05
    • 1970-01-01
    • 2017-12-07
    相关资源
    最近更新 更多