【问题标题】:ARM - Determine a computer is a Big-Endian or a Little-EndianARM - 确定计算机是 Big-Endian 还是 Little-Endian
【发布时间】:2017-06-14 11:24:15
【问题描述】:

我是汇编新手,尤其是 ARM。我试图弄清楚如何阅读以下程序如何确定计算机是 Little-Endian 还是 Big-Endian:

MOV R0, #100
LDR R1, =0X0ABCD876       ;R1 = 0X0ABCD876
STR R1, [R0]
LDRB R2, [R0, #1]

非常感谢!

【问题讨论】:

  • 它不能“确定”任何东西,你可能省略了那部分。它所做的只是将一个字写入内存,然后取回它的第二个字节。测试会告诉你字节顺序(因为它决定了内存中的字节顺序)。 PS:代码看起来很可疑,R0 看起来根本不像指针。你复制对了吗?
  • 虽然许多 ARM 微控制器都可以选择运行大端和小端,但几乎每个人都选择小端。
  • @Jester 我认为你对这个函数的功能是正确的。您能否向我解释一下汇编(ARM)中的指针是如何工作的?我对它不是很熟悉。谢谢!
  • 一般来说,最好使用架构的本地字节序。 xscale 是一个例外,因为他们做错了,可能是故意的,运行 big endian 会导致编译器噩梦。不仅仅是一个手臂的东西,而是任何支持多个平台的平台(TI 在他们的 Cortex-R 上犯了同样的错误,基本上,具有正常外观部件号的一种风格是错误的字节序)。是的,这些工具要好一些。以及较新的 arm 内核,您可以在整个程序或处理器不为大端的情况下进行交换读取。

标签: assembly arm endianness


【解决方案1】:
MOV R0, #100
LDR R1, =0X0ABCD876       ;R1 = 0X0ABCD876
STR R1, [R0]
LDRB R2, [R0, #1]

汇编中没有指针。但是,如果您对 C 有足够的了解以知道指针是什么,那么它只是您正在访问的地址或偏移量的地址。这里的存储和加载使用 R0 作为这些操作的基地址。因此,您基本上是指向某个内存位置,其地址在 r0 中,就像在 C 中您指向某个内存位置,其地址包含在变量中,其语法使其成为指针。

它将值 100 硬编码到 r0 中,这看起来确实像你把它复制错了,但是 100 是 0x64 低两位是零,所以你不会得到对齐错误,我假设代码真的是 mov r0,#0x100但无论如何。

下一行是 arm 汇编器目前支持的语法技巧。通常用于标签。

ldr r3,=hello
nop
nop
nop
b .
hello: .word 0x12341234

给予

00000000 <hello-0x14>:
   0:   e59f3010    ldr r3, [pc, #16]   ; 18 <hello+0x4>
   4:   e1a00000    nop         ; (mov r0, r0)
   8:   e1a00000    nop         ; (mov r0, r0)
   c:   e1a00000    nop         ; (mov r0, r0)
  10:   eafffffe    b   10 <hello-0x4>
00000014 <hello>:
  14:   12341234    eorsne  r1, r4, #52, 4  ; 0x40000003
  18:   00000014    andeq   r0, r0, r4, lsl r0

请帮我把标签hello的地址放到r3中,谢谢。否则我必须这样做:

ldr r3,hello_add
nop
nop
nop
b .
hello: .word 0x12341234
hello_add: .word hello

00000000 <hello-0x14>:
   0:   e59f3010    ldr r3, [pc, #16]   ; 18 <hello_add>
   4:   e1a00000    nop         ; (mov r0, r0)
   8:   e1a00000    nop         ; (mov r0, r0)
   c:   e1a00000    nop         ; (mov r0, r0)
  10:   eafffffe    b   10 <hello-0x4>

00000014 <hello>:
  14:   12341234    eorsne  r1, r4, #52, 4  ; 0x40000003

00000018 <hello_add>:
  18:   00000014    andeq   r0, r0, r4, lsl r0

为了得到相同的结果需要更多的输入。

因此,如果 ldr r7,=something 意味着某事是一个地址,而该语法意味着将该地址加载到寄存器中,那么如果某事是一个数字,那么汇编器就会为我输入该数字。我也可以偷懒少打字。

ldr r3,0x11223344
nop
nop
nop
b .

00000000 <.text>:
   0:   e59f300c    ldr r3, [pc, #12]   ; 14 <.text+0x14>
   4:   e1a00000    nop         ; (mov r0, r0)
   8:   e1a00000    nop         ; (mov r0, r0)
   c:   e1a00000    nop         ; (mov r0, r0)
  10:   eafffffe    b   10 <.text+0x10>
  14:   11223344            ; <UNDEFINED> instruction: 0x11223344

最终结果是我们将这个常量放入寄存器。 arm 和 mips 以及其他固定(ish)长度的指令集对立即数有限制,因此不适合 arm 指令的立即数会导致它添加一些数据并像上面一样执行此 pc 相对负载,但如果它适合然后

ldr r3,=0x100
nop
nop
nop
b .


00000000 <.text>:
   0:   e3a03c01    mov r3, #256    ; 0x100
   4:   e1a00000    nop         ; (mov r0, r0)
   8:   e1a00000    nop         ; (mov r0, r0)
   c:   e1a00000    nop         ; (mov r0, r0)
  10:   eafffffe    b   10 <.text+0x10>

现在我们希望汇编程序已被告知您要使用哪种字节序,实际上如果您不这样做,那么您就有麻烦了,它可能无法正常工作。所以尽管 be-8 或 be-32 让我们假设评论是正确的。

那么 STR 是 32 位存储,请阅读您的手册。到 r0 中包含的地址。因此,如果这是 le 或 be-32,则写入地址 100 获得字节 0x76,地址 101 获得字节 0xd8,地址 102 获得字节 0xBC,地址 103 获得 0x0A。如果是8,那么地址100得到0x0A,地址101得到0xBC,地址102得到0xD8,地址103得到0x76。

ldrb 是说在地址 r0+1 (即 101)处获取一个字节并将其放入 r2 中,很确定它不会对它进行符号扩展。因此,如果 le 则 r2 将包含 0xD8,如果 be-32 则 r2 将获得 0xBC,如果 be-8 则 r2 将包含 0xBC。正如 Jester 所说,您可以比较一下 BE 与 LE。

BE-32 表示字不变,字操作(LDR/STR/LDM/STM)不交换,非字(LDRB、LDRH、STRB、STRH)交换。 BE-8 表示字节操作不交换(字节不变),但非字节操作(字)进行交换。所以在这种情况下,通过混合一个字操作和一个字节操作,其中一种交换和一种不依赖于大端的风格,但对于小端来说,两者都不交换。

当然,如果汇编器没有正确加载 r1(这是整个工作的关键),那么这是一个字操作,可能会或可能不会再次交换。会更安全

mov r1,#0x0A000000
orr r1,r1,#0x00BC0000
orr r1,r1,#0x0000d800
orr r1,r1,#0x00000076

然后不用担心 pc 相对负载交换和/或汇编器放置交换的值,因此它会根据架构在途中取消交换。所以你必须正确设置架构并要求大端。

【讨论】:

    猜你喜欢
    • 2011-10-06
    • 1970-01-01
    • 2020-12-01
    • 2019-06-30
    • 2018-05-15
    • 2022-06-10
    • 1970-01-01
    • 2014-05-25
    • 2012-10-09
    相关资源
    最近更新 更多