【问题标题】:How to declare buffer in ARM Assembly如何在 ARM 程序集中声明缓冲区
【发布时间】:2015-10-20 01:06:18
【问题描述】:

我的程序的目标是从命令行向寄存器 r0 传递一个整数的 ASCII 字符串。

然后我必须将 ASCII 字符串转换为有符号整数并在 r0 中返回,这是在过程 atoi 中完成的,并且它工作得很好。

然后我必须初始化一个缓冲区,并调用过程 itoa,其中 r0 包含整数,r1 包含缓冲区的地址。

我遇到的第一个问题,我认为有很多问题,我似乎无法初始化和声明缓冲区,我该怎么做?

到目前为止,这是我的代码: 。文本 .global _start .equ 出口,1 .equ 写,4 .equ 标准输出,1

_start:
    ldr r5, [sp]        @argc value
    ldr r6, =1
    mov r8, #8          @argv address

    ldr r4, [sp, r8]        
    add r8, r8, #4          
    mov r0, r4
    bl atoi
    ldr r1, =buffer 
    bl itoa
    ldr r0, =1
    bl println
    mov r0, #0      @ success exit code
    mov r7, #exit
    svc 0           @ return to os

atoi:
    push {r4, lr}
0:
    ldrb r1, [r0], #1
    cmp r1, #'-
    beq 2f
    cmp r1, #'0
    blo 1f
    cmp r1, #'9
    bhi 1f
    sub r1,r1,#'0
    ldr r3, =0
    mov r3,r2,lsl#3
    add r2,r2,r2
    add r2,r2,r3
    add r2,r2,r1
    bal 0b

1:  cmp r4, #1
    rsbeq r2, r2, #0
    mov r0, r2
    pop {r4, pc}

2:  
    ldr r4, =1
    bal 0b
    
itoa: 
    push {r4, r5, lr}
    mov r4, r1

    
    ldr r5, =0
    push {r5}
    cmp r0,#0
    bgt 4f

    0:  ldr r5, =45
    strb r5, [r4] , #1
    rsb r0, r0, #0

4:  b qr10

3:  add r1, r1, #'0
    push {r1}
    cmp r0, #0
    bne 4b

1:  pop {r5}
    cmp r5, #0
    beq 2f
    strb r5, [r4] , #1
    bal 1b

2:  ldr r1, =buffer 
    pop {r4,r5, pc}
    
    

qr10:
    mov r3, r0      @ save dividend (n)
    ldr r1, =0x1999999a @ 2^32/10
    sub r0, r0, r0, lsr #30 @ adjust for large dividends
    umull r2, r0, r1, r0    @ quotient in r0 (q)
    mov r1, r0, LSL #3  @ 8q
    add r1, r1, r0, LSL #1  @ 10q
    sub r1, r3, r1      @ remainder in r1 (r = n - 10q)
    b 3b



# determine string length
# parameters
#   r0:   address of null-terminated string
# returns
#   r0:   length of string (excluding the null byte)
# modifies r0, r1, r2
strlen:
    @ push {lr}
    mov r1, r0      @ address of string
    mov r0, #0      @ length to return
0:
    ldrb r2, [r1], #1   @ get current char and advance
    cmp r2, #0      @ are we at the end of the string?
    addne r0, #1
    bne 0b
# return
    @ pop  {pc}
    mov pc, lr      @ can do this instead of using the stack

# write a null-terminated string followed by a newline
# parameters
#   r0:  output file descriptor
#   r1:  address of string to print
# modifies r0, r1, r2
println:
    push {r4, r5, r7, lr}
# first get the string length
    mov r4, r0      @ save the fd
    mov r5, r1      @ and the string address
    mov r0, r1      @ the string address
    bl strlen       @ returns the string length in r0
    mov r2, r0      @ put length in r2 for the WRITE syscall
    mov r0, r4      @ restore the fd
    mov r1, r5      @ and the string address
    mov r7, #write
    svc 0
    mov r0, r4      @ retrieve the fd
    adr r1, CR      @ get the address of the CR string
    mov r2, #1      @ one char to write
    mov r7, #write
    svc 0
    pop {r4, r5, r7, pc}    @ restore registers and return to caller

    CR: .byte '\n
    .data
    buffer:  .space 32

【问题讨论】:

  • 我已经编辑了代码并且它确实可以工作,除非我尝试将 r0 与 #0 进行比较,如果它小于 0 则分支到 0b。问题是即使值 132 它也总是分支这显然大于 0。知道为什么吗?但是,当我删除添加的代码时,它可以完美运行,添加代码背后的想法是支持负数...
  • 别在意我之前的评论,这是位置问题,我已经发布了适当的代码并且它有效!非常感谢

标签: assembly arm buffer


【解决方案1】:

编辑:要在数据段中分配缓冲区,请使用 SPACE 指令:

buffer: SPACE 16

由于 SPACE 是汇编器指令而不是 CPU 命令,因此在您的汇编器中可能会有所不同。

要将地址加载到 r1 中,请将缓冲区的地址放入函数结束后代码段中的寄存器大小的常量,然后使用 LDR 加载:

mov pc, lr
p_buffer: dcd buffer

然后在需要的地方加载:

ldr r1, p_buffer

现在 r1 包含了 p_buffer 的内容,也就是缓冲区的地址。同样,语法可能会有所不同。

【讨论】:

  • 我不明白,你说从 SP 中减去所需的缓冲区大小是什么意思?我也可以不使用堆栈吗?我可以在 r1 中获得缓冲区的地址吗?并为我的缓冲区分配 16 个字节?
  • 我看到您在.data 部分中已经有一个缓冲区 - 是您要使用的缓冲区,只是不确定如何将其地址加载到 r1 中?
  • 它似乎不起作用......它没有写入缓冲区,可能是因为它没有初始化/没有足够的大小......
  • 检查 r1 的值。可以调试吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-17
  • 2018-03-05
  • 2012-02-07
  • 2022-11-12
相关资源
最近更新 更多