【发布时间】:2020-06-02 15:14:59
【问题描述】:
我在u-boot/arch/arm/lib/semihosting.c 中找到了以下代码,它使用bkpt 和其他指令并提供输入和输出操作数,即使它们未在ASM 模板中指定:
static noinline long smh_trap(unsigned int sysnum, void *addr)
{
register long result asm("r0");
#if defined(CONFIG_ARM64)
asm volatile ("hlt #0xf000" : "=r" (result) : "0"(sysnum), "r"(addr));
#elif defined(CONFIG_CPU_V7M)
asm volatile ("bkpt #0xAB" : "=r" (result) : "0"(sysnum), "r"(addr));
#else
/* Note - untested placeholder */
asm volatile ("svc #0x123456" : "=r" (result) : "0"(sysnum), "r"(addr));
#endif
return result;
}
最小的、可验证的例子:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
register long result asm("r0");
void *addr = 0;
unsigned int sysnum = 0;
__asm__ volatile ("bkpt #0xAB" : "=r" (result) : "0"(sysnum), "r"(addr));
return EXIT_SUCCESS;
}
根据ARM架构参考手册bkpt指令
采用单个 imm 参数,根据我对GCC manual
section on inline assembly 的阅读,GCC 不允许提供操作数,如果它们
模板中没有指定。使用-S 生成的输出程序集:
.arch armv6
.eabi_attribute 28, 1
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file "bkpt-so.c"
.text
.align 2
.global main
.arch armv6
.syntax unified
.arm
.fpu vfp
.type main, %function
main:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #12
mov r3, #0
str r3, [fp, #-8]
mov r3, #0
str r3, [fp, #-12]
ldr r2, [fp, #-12]
ldr r3, [fp, #-8]
mov r0, r2
.syntax divided
@ 10 "bkpt-so.c" 1
bkpt #0xAB
@ 0 "" 2
.arm
.syntax unified
mov r3, #0
mov r0, r3
add sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.size main, .-main
.ident "GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0"
.section .note.GNU-stack,"",%progbits
那么"=r" (result) : "0"(sysnum), "r"(addr) 在这行中有什么意义:
__asm__ volatile ("bkpt #0xAB" : "=r" (result) : "0"(sysnum), "r"(addr));
?
【问题讨论】:
-
函数名包含
trap...所以这些很可能是某种系统调用。陷阱处理程序大概使用r0来接收和返回值。 -
我很难理解编译器应该从这一行生成哪些汇编指令。
-
@user1042840 你真的看过生成的程序集吗?
-
@ThomasJager:是的,我做了,粘贴了。它只显示 bkpt #0xAB 尽管例如如果 addr 改变了周围的线会改变。我最想知道的是 GCC 应该如何理解这样的行以及这种行为记录在哪里?
标签: assembly gcc arm inline-assembly semihosting