我想为我的ARMv7平台编写一个简单的有效负载。首先,我尝试了一个通过UART发送字符的简单循环:
void payload()
{
while(1)
{
USART3->DR = 0x68;
}
}
08000358 <payload>:
8000358: b480 push {r7}
800035a: af00 add r7, sp, #0
800035c: 4b01 ldr r3, [pc, #4] ; (8000364 <payload+0xc>)
800035e: 2268 movs r2, #104 ; 0x68
8000360: 809a strh r2, [r3, #4]
8000362: e7fb b.n 800035c <payload+0x4>
8000364: 40004800 andmi r4, r0, r0, lsl #16
字符串
这是我想要的有效载荷,一次在C中,一次在汇编中。
int main()
{
uint32 buffer[4];
buffer[0] = 0xaf00b480;
buffer[1] = 0x22684b01;
buffer[2] = 0xe7fb809a;
buffer[3] = 0x40004800;
memcpy(0x20004000,&buffer,4*sizeof(uint32));
goto *(void *)((uint32_t) buffer | 1);
return 0;
}
型
这工作得很好,字符通过UART发送。现在,我想在payload中调用一个函数:
void payload()
{
while(1)
{
USART3->DR = 0x68;
asm volatile(
"bl 0x08000348\n"
);
}
}
08000358 <payload>:
8000358: b480 push {r7}
800035a: af00 add r7, sp, #0
800035c: 4b02 ldr r3, [pc, #8] ; (8000368 <payload+0x10>)
800035e: 2268 movs r2, #104 ; 0x68
8000360: 809a strh r2, [r3, #4]
8000362: f7ff fff1 bl 8000348 <function>
8000366: e7f9 b.n 800035c <payload+0x4>
8000368: 40004800 andmi r4, r0, r0, lsl #16
型
同样,我想要的有效载荷,一次在C中,一次在汇编中。
void function()
{
asm volatile(
"nop\n"
"nop\n"
);
}
int main()
{
uint32 buffer[5];
buffer[0] = 0xaf00b480;
buffer[1] = 0x22684b02;
buffer[2] = 0xf7ff809a;
buffer[3] = 0xe7f9fff1;
buffer[4] = 0x40004800;
memcpy(0x20004000,&buffer,5*sizeof(uint32));
goto *(void *)((uint32_t) buffer | 1);
return 0;
}
型
字符现在只发送3次,然后我会崩溃(处理器的故障处理程序)。我检查了函数的内存区域和我的缓冲区,两者看起来是一样的:
0x8000358 <payload>: 0xaf00b480 0x22684b02 0xf7ff809a 0xe7f9fff1
0x8000368 <payload+16>: 0x40004800 0xb082b580 0xf001af00 0x2102f863
0x20004000 <_heap+3144>: 0xaf00b480 0x22684b02 0xf7ff809a 0xe7f9fff1
0x20004010 <_heap+3160>: 0x40004800 0x00000000 0x00000000 0x00000000
型
1条答案
按热度按时间mm9b1k5b1#
后藤 *(void *)((uint32_t)buffer| 1);
奇怪的是,对于使用不必要的内联汇编的人来说,这里可以使用一些。
当我编译它时,我得到:
字符串
这应该马上就会失败
来自手臂文件:
ADD(寄存器)和MOV(寄存器)分支,无互通。
你能做的就是用一些真实的的asm
型
现在,如果你不想要分支链接,而是一个分支,因为你是自由和松散的内联汇编,这更像你的风格,不应该有mov问题,至少我的编译器生成。顺便说一句,我们需要看看你的编译器生成了什么,看看为什么你没有立即崩溃。
型
bx可以用来这让它感觉更好
型
一旦fifo不再填充字符,您就不能那样对待uart数据寄存器。
你也不能复制这段代码并那样运行它。
型
只要8000348保持功能所在位置,就可以内置在闪存中,但BL是PC相关的,因此如果您想将其复制到SRAM(我知道我自己问题的答案,将让您弄清楚我是如何知道的,这是一个微控制器,因此您的意思是询问armv7-m而不是armv7)。
型
我想你没有把function()复制到0x 20003 FF 0?运行此程序时,在该地址上有哪些数据?拆开后看起来像什么?
所以你是“得到它”的大部分与汇编语言,但错过了一些事情。
现在你可以做的就是编写你想要的代码:
型
无需链接
型
用你的风格
型
用我的编译器给出:
型
仍然有点像你的代码,但现在你可以重新定位这段代码,从一个4字节对齐的地址开始,它不会有不能调用函数的问题。
是的,我在这个例子的链接上作弊了,我没有 Bootstrap 。还有一点让我很困扰,他们默认使用堆栈帧,真是浪费。我想知道我是否可以在没有它的情况下构建我的工具链。它确实使这个黑客解决方案更好地工作,否则:
型
然后可以使用
型
是的,duh,你不需要orr a 1来运行工具链应该已经处理好了。
型
现在有一个内联的asm魔术,你可以把buffer的地址加载到r3中,而不必依靠反汇编代码来解决这个问题。请注意,因为您似乎使用的是armv7-m,尽管将其称为armv7。你可以使用thumb 2指令或r3,r3,#1,这在心理上是正确的,你想或在那里的位不添加它。但是如果这是一个armv 6-m,比如cortex-m0,或者你想要可移植性,那么就像add r3,#1一样丑陋地执行add,因为这不是一个thumb 2指令,而且是可移植的。
所以,如果你得到了一些字符,我怀疑你的后藤工作不知何故,再次听起来像你是使用qemu也许?也许这就是为什么?但不是试图在sram中运行代码的副本,你向后分支找到function(),但在那里找到了数据,这要么使你崩溃,要么因为这是在复制代码之前,它再次运行了几次复制的代码,无论是什么,最终都偏离了轨道。或者可能是因为你没有正确使用uart,你使缓冲区溢出,在这些品牌中的至少一个上,这可能导致uart停止工作,直到你清除缓冲区溢出标志。假设您依赖于uart输出来查看成功或失败。(你会看到,当运行这个程序时,没有调用函数,这使我相信这是一个模拟,而不是真实的的硬件,或真正的硬件,你只是看到一小部分的值,你是推到uart)。
试试这个
型
作为你的起点,看看我在说什么,如果你看到0123456701234567永远,那么我怀疑你是在使用模拟器,而不是硬件。
编辑:
orr 1是后藤的问题,你可以这样做:
型
EDIT2
程序已经在SRAM中,你只是简单地将它从SRAM复制到SRAM......如果复制是“利用”,那么好,但在微控制器上,你不会将此复制到其他代码之上,大多数时候,所有代码都会耗尽闪存,所以一个SRAM位置和另一个一样好。不管怎样,这个术语不是问题所在。
在您下面的评论中
在main中,我分支到地址0x 20004001。
不,这是同一个错误,如果你想用一个地址或你需要使用正确的指令。
型
我电脑上的编译器
型
当链接时,它仍然可以工作。
但如果你这么做
型
与此答案的顶部相同的bug:
ADD(寄存器)和MOV(寄存器)分支,无互通。
在arm文档中搜索该行和/或该术语。