如果你问这个问题是因为你有一个任务,那么你的目标可能应该是花费尽可能多的时间来构建你自己的、有效的、解决方案:在我看来,这是最好的学习方式。
qemu-system-aarch64
这比使用、和逐步组装、链接和调试 aarch64 程序要aarch64-elf-as
容易。aarch64-elf-ld
aarch64-elf-gdb
这可以在 Linux 和 Windows 上完成——我使用的是 Windows 环境。工具链是从这里下载的,qemu-system-aarch64
从这里下载。
如果您对基数/基数转换感到不舒服,请先在 Internet 上查找教程,例如这个。只有这样,您才应该开始努力寻找解决问题的方法。
ARM 在其“探索性工具”中提供的文档绝对是最好的,恕我直言,当它详细解释 aarch63 指令集时。
你的问题可以分为两部分:
- 将ASCII中的字符串(即“43”)转换为其二进制表示形式 101011。
- 将 101011 二进制数转换为其字符串表示形式,即“101011”。
下面的示例不对输入执行任何验证,它通常应该做什么:
/* ----------------------------------------------------
* A minimalist section of code for converting a
* zero-terminated string representating a decimal
* number into a zero-terminated string representating
* a binary number.
* --------------------------------------------------*/
.title "dec2bin.s"
.arch armv8-a
.text
.section .text.startup,"ax"
.globl Reset_Handler
Reset_Handler: ldr x0, =decimalsz // load address of decimalsz into x0.
mov x2, xzr // use x2 for computing the binary value - initial value is zero.
decascii2bin: ldrb w1, [x0], #1 // load byte pointed by x0, then increment x0 by 1.
cbz x1, bin2binascii // if x1 does contain zero, we reached the end of the input buffer.
sub w1, w1, #'0' // x1 does contain the ASCII value for character '4' or '3' - substracting ASCII value for '0'.
// we need to multiply the previous result by 10, then add the current digit:
add x3, xzr, x2, lsl #3 // x3 = 0 + x2 << 3, i.e. 8 * x2
add x2, x3, x2, lsl #1 // x2 = x3 + x2 < 1, i.e. 8 * x2 + 2 * x2 = 10 *x2
add x2, x2, x1 // if we are processing '4', x2 = x2 (0) * 10 + 4 = 4. if we are processing '43, x2 = x2 (40) * 10 + 3 = 43.
bl decascii2bin
bin2binascii: // x2 does now contain 43.
ldr x0, =binarysz // load address of binarysz into x0.
add x0, x0, #64 // x0 points to the byte which would contain the zero-termination if 32 bits were to be displayed.
clz x1, x2 // retrieve the number of bits set to zero for the number contained in x2.
sub x0, x0, x1 // number 43 begins with 58 zero bits, therefore we will only display 64 - 58 = 6 bits.
strb wzr, [x0], #-1 // store zero at binarysz + 6.
movk x3, #'0' // store '0' in x3.
nextbit: bfxil x3, x2, #0, #1 // extract 1 from x2 starting from most significant bit 0, and insert at low end of x3, leaving other bits unchanged.
strb w3, [x0], #-1 // store '0' or '1' to the byte location pointed by x0, then decrement x0 by one.
lsr x2, x2, #1 // shift x2 to the right by one bit.
add x1, x1, #1 // increment number of leading zero bits + number of bits processed, 58 + 1 at first pass, up to 64.
cmp x1, #64 // we are done of 64 bits were leading zero bits or processed.
b.ne nextbit
done: b.al done
.balign 16
// maximum possible value for un unsigned uint_64_t in decimal is:
// 18446744073709551615.
decimalsz: .asciz "43"
// maximum possible value for un unsigned uint_64_t in binary is:
// 1111111111111111111111111111111111111111111111111111111111111111.
// we need at most 65 bytes for 64 digits and a \0.
binarysz: .asciz "0000000000000000000000000000000000000000000000000000000000000000"
.end
组装/链接示例:
aarch64-elf-as -g -adhln -o dec2bin.o dec2bin.s > dec2bin.lst
aarch64-elf-ld -gc-sections -g -e Reset_Handler -Ttext-segment=0x42000000 -Map=dec2bin.map -o dec2bin.elf dec2bin.o
启动 qem:
qemu-system-aarch64 -m 256M -semihosting -machine virt,gic-version=2,secure=on,virtualization=on -S -gdb tcp::1234,ipv4 -monitor telnet:127.0.0.1:1235,server,nowait -cpu cortex-a53 -nographic -kernel dec2bin.elf
启动 GDB(在其他 Windows 控制台/Linux shell 中):
aarch64-elf-gdb dec2bin.elf
GNU gdb (GDB) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-w64-mingw32 --target=aarch64-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from src\dec2bin\dec2bin.elf...done.
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
Reset_Handler () at dec2bin.s:13
13 ldr x0, =decimalsz // load address of decimalsz into x0.
您现在可以逐步执行程序,并使用 和 命令检查寄存器和stepi
输出p/x {$x0, $x1, $x2, $x3}
缓冲区x/s binarysz
。
当你到达 done: 时,你可以检查结果,然后退出 GDB:
35 done: b.al done
(gdb) p/x {$x0, $x1, $x2, $x3}
$9 = {0x42000062, 0x40, 0x0, 0x31}
(gdb) x/s binarysz
0x42000063 <binarysz>: "101011"
(gdb) kill
Kill the program being debugged? (y or n) y
[Inferior 1 (Remote target) killed]
(gdb) quit