我有下一个可怕的代码:
void print(const char* text) {
unsigned long address = 0x9000000;
unsigned long counter = 0;
char ch = *text;
while (ch != '\0') {
address += counter;
asm volatile(
"MOV X10, %[address];"
"MOV W9, %w[ch];"
"STRB W9, [X10];"
:[address]"+r"(address), [ch]"+r"(ch)
);
++counter;
ch = *(text + counter);
}
}
void start(void) {
print("Hello, World!");
}
不幸的是,即使这段代码也不能正确工作,并打印:Hel
而不是Hello, World!
然而,我更愿意重写嵌入/内联汇编器中的所有循环逻辑,但我不知道如何在汇编器中读取和重写C数组(text
)。我尝试了很多变种,都失败了。
这段代码是为aarch 64(cortex-a72)创建的,它在Qemu中通过命令启动:
qemu-system-aarch64 -M virt \
-cpu cortex-a72 \
-bios "/opt/homebrew/Cellar/qemu/$(QEMU_VERSION)/share/qemu/edk2-aarch64-code.fd" \
-m 128M \
-nographic \
-device loader,file=$(BUILD_DIR)/kernel.elf \
-device loader,addr=0x40100000,cpu-num=0
**P.S.**我在macOS(M1 Pro)上使用LLVM clang和aarch 64-elf-binutils编译器和链接器来构建kernel.elf
。
2条答案
按热度按时间7vux5j2d1#
address
未正确递增。让我们通过打印到
stdout
来查看这个问题。输出
我怀疑OP只想在打印后将
address
更改为1 *。2exbekwf2#
哦,也许有人是像我一样的菜鸟,这将帮助他。
首先,解决方案:
它是如何工作的?
1.解压缩视频存储器的地址(如果我错了,请纠正我)。在我们的例子中是
0x9000000
。1.将
address
和text
变量加载到X10
和X11
寄存器中(没有严格的规则可以使用哪些寄存器)。注意text
是一个指针,所以实际上我们将字符串的地址加载到寄存器中,而不是值。1.将
X11
寄存器中的地址所定位的下一个字符串字符加载到X9
寄存器中。1.将加载的值复制到
0x9000000
。1.递增
X11
寄存器的值,换句话说,我们只是将指针切换到字符串中的下一个字符。1.最后,如果
W9
寄存器包含非零值(C字符串以\0
结束),则跳转到PRINT_STR
。**UPD:**第二个想法是最好的......我想使用汇编程序,因为我认为C代码将是丑陋的,仍然与汇编程序混合。但我忘了这是先生。C,指针就是力量!