【问题标题】:MIPS Assembly - String (ASCII) InstructionsMIPS 汇编 - 字符串 (ASCII) 指令
【发布时间】:2011-10-22 01:57:30
【问题描述】:

我正在用 C 语言编写一个用于 MIPS 汇编的汇编程序(因此它将 MIPS 汇编转换为机器代码)。

现在 MIPS 有三种不同的指令:R-Type、I-Type 和 J-Type。但是,在.data。部分,我们可能有类似message: .asciiz "hello world" 的内容。在这种情况下,我们如何将 ASCII 字符串转换为 MIPS 的机器码?

谢谢

【问题讨论】:

    标签: c string assembly ascii mips


    【解决方案1】:

    ASCII 文本不会转换为机器码。它以Wikipedia 上的格式存储。

    MIPS 使用这种格式来存储 ASCII 字符串。特别是.asciiz,就是字符串加上NUL字符。因此,根据工作表,A 是十六进制的41,二进制是0100 0001。但是不要忘记 NUL 字符,所以:0100 0001 0000

    在存储字符串时,我会采用Mars MIPS simulator 的想法,只需在内存中的已知地址处启动内存部分,并将对标签message 的任何引用设置为内存中的该位置。

    请注意,数据部分中的所有内容都不是 R-type、I-type 或 J-type。这只是原始数据。

    【讨论】:

    • 并且假设输入字符集也是 ASCII(或者可能是 UTF-8),因此汇编程序应该简单地将字节从源文件复制到输出文件(在当前输出位置),最多引用字符串的结尾。尽管您确实需要处理 C 风格的转义序列,例如 \n = 0xa (LF = linefeed)。
    【解决方案2】:

    数据不可执行,不应转换为机器码。它应该以适合您目标的数据类型的正确二进制表示形式进行编码。

    【讨论】:

    • 是的,我知道这一点。我的.data 只能有.word.asciiz。如果是.word,那么我只需将数字转换为它的 32 位表示。但是您如何将.asciiz 表示为机器代码指令?我需要将其转换为机器代码。所以array: .word 0:10 将创建 10 条指令:000000000000000000000000000001010
    • .asciiz 不是机器代码指令,而是汇编指令。它告诉汇编器它应该以某种格式将这些数据存储在最终的二进制文件中。换句话说,汇编器负责将您的数据表示转换为正确的二进制格式,并将其存储在可执行文件中。
    • 您不会将 .asciiz 表示为机器代码指令。假设您正在实现一个相当标准的 ABI,您会将其存储为一个字节序列,每个字节包含一个字母的 ASCII 值,后跟一个 NUL 终止符。
    • 对了。我很抱歉使用“机器代码指令”。我的意思是“字节序列”。谢谢。
    【解决方案3】:

    正如其他答案所指出的,.ascii "string" 指令中包含的 ascii 在目标文件的数据段中以原始二进制格式编码。至于从那里发生什么,这取决于汇编程序编码成的二进制格式。 通常数据不会被编码成机器码,然而GNU as 会很高兴地组装这个:

    .text
    start:
      .ascii "Hello, world"
      addi $t1, $zero, 0x1
    end:
    

    如果你反汇编 objdump 中的输出(我在这里使用 mips-img-elf 工具链)你会看到:

    Disassembly of section .text:
    
    00000000 <message>:
       0:   48656c6c    0x48656c6c
       4:   6f2c2077    0x6f2c2077
       8:   6f726c64    0x6f726c64
       c:   20090001    addi    t1,zero,1
    

    十六进制序列48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 拼出“Hello, world”。 我来这里是在寻找 GAS 为何如此行为的答案时。 Mars不会汇编上面的程序,报错数据指令不能在文本段中使用 有人对此有任何见解吗?

    【讨论】:

    • 洞察什么?为什么 MARS 在其汇编器上有训练轮,并且不允许您在 asm 源要求的地方组装任意字节?通常你会将字符串放在.section .rodata 中,在那里它们将作为文本段的一部分被链接,但将它们放在文本部分中它们不会被执行的地方是完全可以的。或者使用.byte 0x20, 0x09, 0x00, 0x01 或其他东西手动编码指令。 (通常没有理由这样做,但如果你愿意,你可以这样做。)
    • 但是如果你不明白你在做什么,很容易将数据放在执行的地方,这可能会让初学者感到困惑,因此 MARS 中的训练轮/nerf 填充.我认为它的模拟器/模拟器确实从 MIPS 机器代码运行你的程序,所以我不认为 MARS 直接“组装”到模拟器内部,并将 .text 部分限制为只能从文本中解析的 asm 指令。
    • 嗨,彼得,感谢您的回复。我不关心 MARS 的行为,我感兴趣的是为什么 GAS 允许您使用 .ascii 指令将原始字节编码到 .text 部分。我认为您刚刚回答了这个问题,尽管您说您可以使用这些指令将任意二进制数据放置在您喜欢的任何位置,可能用于手动编码指令。我又看了一遍,是的,objdump 将尝试将您使用这些指令插入的二进制数据解释为指令。
    • 对,objdump 无法判断字节是如何到达那里的。这只是汇编器输出文件中的字节。 MARS 绝对是个例外。大多数汇编器就像 GAS 一样,会很高兴地将一行 asm 源代码汇编成当前部分中的字节。由程序员来确保它是有用的。
    • 感谢您解决此问题。这种看待事物的方式非常合理,并解释了为什么 GAS 允许这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    相关资源
    最近更新 更多