【问题标题】:ARM Assembly: write number located on stackARM 程序集:写入位于堆栈上的数字
【发布时间】:2017-10-11 16:27:37
【问题描述】:

我有一个 ARM 汇编代码,atm 只是从字符串变量中打印出“Hello World”:

  .global _start

_start:
    mov r0, #40
    mov r1, #25
    bl func1
    mov r7, #1
    swi 0

func1:
    push {lr}
    add r2,r0,r1
    mov r0,r2
    bl func2
    pop {pc}

func2:
    mov r7, #4
    mov r0, #1
    mov r2, #12
    ldr r1, =string

    swi 0
    bx lr

.data
    string:
    .ascii "Hello World\n"

但是,现在我想打印 func1 (result = 65) 中发生的加法结果,方法是将其写入堆栈,然后将 write() 系统调用交给堆栈上结果的内存地址。 我已经尝试将 func2 开头的结果推入堆栈

push {r0}

然后通过访问堆栈指针和偏移量 4 以某种方式加载 r1 中的地址(它存储要为 write() 系统调用打印的参数),如果我正确,则应该存储该值:

ldr r1, [sp, #4]

但这似乎不起作用,我这样尝试的所有东西都会出现分段错误。

谁能帮助我了解如何获取结果堆栈上的地址内存,然后使用 write() 系统调用继续打印它?如果它将结果打印为字母而不是数字(因为它可能会将其解释为 ASCII 值),我可以接受,这只是让我了解如何获取堆栈上值的地址并打印它。 非常感谢:)

【问题讨论】:

    标签: assembly arm


    【解决方案1】:

    要获取地址超过sp 4 个字节,您可以使用add r1, sp, #4。但是请记住,push 以完全降序模式使用堆栈,这意味着 sp 指向最后推送的项目。因此你不需要添加4,你可以添加mov r1, sp

    您对ldr 所做的实际上是从堆栈中加载值,即使您使用了正确的偏移量,但仍然不好,因为您需要的是地址而不是值。

    【讨论】:

    • 嗯,是的,这是有道理的。但是,如果我将 func2 下的代码更改为此 func2: push {r0} mov r7, #4 mov r0, #1 mov r2, #2 mov r1, sp 它会给我一个分段错误(核心转储)。我在这里还做错了什么?
    • 啊,我认为它会在“未捕获的目标信号 11(分段错误)-核心转储”的消息之前打印出一个“A”,所以它似乎是这样工作的 :) 为什么会这样虽然,我仍然得到分段错误,尽管它将值 #65 打印为 ASCII 值?每次像这样访问堆栈指针时都会发生这种情况吗?
    • 当然不是,故障在别处。例如,您可能忘记从堆栈中弹出值。
    • 为什么我需要从堆栈中弹出值?我只想从我需要解决的堆栈中读取它。考虑到我上面的代码从我的第一条评论到您的初始答案的变化,知道为什么会发生分段错误吗?
    • 因为你的func1pop {pc},如果在那里找到你的号码而不是之前推送的lr 会很不高兴。使用调试器查明故障所在。
    猜你喜欢
    • 2014-11-28
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 2016-04-18
    • 2015-09-03
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    相关资源
    最近更新 更多