关于寄存器的ARM汇编MOV和LDR

时间:2015-12-09 17:01:46

标签: assembly compiler-construction arm

我正在为一个简单的语言规范编写一个编译器,并使用给我的参考编译器,我一直在关注生成的程序集并将其定制到我自己的编译器。

然而,在检查参考编译器生成的程序集的过程中,我很难理解为什么我更改的程序集导致第二个打印不生成任何内容:

.data

msg_0:
    .word 50
    .ascii "NullReferenceError: dereference a null reference\n\0"

msg_1:
    .word 5
    .ascii "%.*s\0"

msg_2:
    .word 3
    .ascii "%d\0"

msg_3:
    .word 1
    .ascii "\0"

.global main
.text

main:
    PUSH {lr}
    SUB sp, sp, #8
    LDR r0, =8
    BL malloc
    MOV r4, r0
    LDR r5, =10
    LDR r0, =4
    BL malloc
    STR r5, [r0]
    STR r0, [r4]
    MOV r5, #'a'
    LDR r0, =1
    BL malloc
    STRB r5, [r0]
    STR r0, [r4, #4]
    STR r4, [sp, #4]
    LDR r4, [sp, #4]
    MOV r0, r4
    BL p_check_null_pointer
    LDR r4, [r4]
    LDR r4, [r4]
    STR r4, [sp, #0]
    LDR r4, [sp, #0]
    MOV r0, r4
    BL p_print_int
    BL p_print_ln
    LDR r4, =42
    LDR r5, [sp, #4]
    MOV r0, r5
    BL p_check_null_pointer
    LDR r5, [r5]
    STR r4, [r5]
    LDR r4, [sp, #4]
    MOV r0, r4
    BL p_check_null_pointer
    LDR r4, [r4]
    LDR r4, [r4]
    STR r4, [sp, #0]
    LDR r4, [sp, #0]
    MOV r0, r4
    BL p_print_int
    BL p_print_ln
    ADD sp, sp, #8
    LDR r0, =0
    POP {pc}
    .ltorg
p_check_null_pointer:
    PUSH {lr}
    CMP r0, #0
    LDREQ r0, =msg_0
    BLEQ p_throw_runtime_error
    POP {pc}
p_throw_runtime_error:
    BL p_print_string
    MOV r0, #-1
    BL exit
p_print_string:
    PUSH {lr}
    LDR r1, [r0]
    ADD r2, r0, #4
    LDR r0, =msg_1
    ADD r0, r0, #4
    BL printf
    MOV r0, #0
    BL fflush
    POP {pc}
p_print_int:
    PUSH {lr}
    MOV r1, r0
    LDR r0, =msg_2
    ADD r0, r0, #4
    BL printf
    MOV r0, #0
    BL fflush
    POP {pc}
p_print_ln:
    PUSH {lr}
    LDR r0, =msg_3
    ADD r0, r0, #4
    BL puts
    MOV r0, #0
    BL fflush
    POP {pc}

此处的程序集由以下代码段

生成
begin
  pair(int, char) p = newpair(10, 'a');
  int f = fst p;
  println f;
  fst p = 42;
  f = fst p;
  println f
end

作为编译器的扩展,我决定进行编译器优化(强度降低/死代码消除/窥孔优化等)。所以我发现以下汇编指令,我认为我将其简化为一条指令:

    LDR r4, [sp, #4]
    MOV r0, r4

        LDR r0, [sp, #4]

所以在主要中,我对上面的说明进行了更改

    LDR r4, [sp, #4]
    MOV r0, r4

    LDR r4, [sp, #0]
    MOV r0, r4

    LDR r5, [sp, #4]
    MOV r0, r5

    LDR r4, [sp, #4]
    MOV r0, r4

    LDR r4, [sp, #0]
    MOV r0, r4

当我进行这些修改时,只有第一条打印指令打印10.它还应该打印42.所以我期待

10
42

但实际上在改变后它是

10

我阅读了手册,发现MOV用于字节值,我们应该将LDR用于大小超过一个字节的任何内容。但为什么这不起作用?

我不明白我在这里做错了什么。

0 个答案:

没有答案
相关问题