我已经开始在 GCC/G++ 下开发一个小型 16 位操作系统。我正在使用 GCC 交叉编译器,它是在 Cygwin 下编译的,我将 asm(".code16gcc\n") 作为每个 .CPP 文件的第一行,使用 Intel ASM 语法和命令行来编译和链接.CPP 文件如下所示:
G++: i586-elf-g++ -c $(CPP_FILE) -o $(OBJECT_OUTPUT) -nostdinc -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fpermissive -masm=intel
LD: i586-elf-ld -T $(LD_SCRIPT) $(OBJECT_OUTPUT) -o $(BINARY_OUTPUT)
Run Code Online (Sandbox Code Playgroud)
我目前面临的问题是GCC 将函数调用代码翻译成汇编的方式。
更具体地说,GCC 不使用 PUSH 指令来传递参数,而是“计算”参数相对于 ESP 的偏移量,然后使用 MOV 指令手动写入堆栈。
这对我来说没有好处,因为我依赖汇编代码中的 PUSH 指令。为了更清楚地说明我的问题,请使用以下两个函数:
void f2(int x);
void f1(){
int arg = 8;
asm("mov eax, 5"); // note: super hacky unsafe use of GNU C inline asm
asm("push eax"); // Writing registers without …Run Code Online (Sandbox Code Playgroud) static int func_name (const uint8_t * address)
{
int result;
asm ("movl $1f, %0; movzbl %1, %0; 1:"
: "=&a" (result) : "m" (*address));
return result;
}
Run Code Online (Sandbox Code Playgroud)
我已经通过互联网浏览了内联汇编参考。但我无法弄清楚这段代码在做什么,例如。$1f 是什么?“m”是什么意思?正常的内联约定不是使用“=r”和“r”吗?
根据http://lxr.free-electrons.com/source/arch/arm/include/asm/atomic.h#L31
static inline void atomic_add(int i, atomic_t *v)
41 {
42 unsigned long tmp;
43 int result;
44
45 prefetchw(&v->counter);
46 __asm__ __volatile__("@ atomic_add\n"
47 "1: ldrex %0, [%3]\n"
48 " add %0, %0, %4\n"
49 " strex %1, %0, [%3]\n"
50 " teq %1, #0\n"
51 " bne 1b"
52 : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
53 : "r" (&v->counter), "Ir" (i)
54 : "cc");
55 }
Run Code Online (Sandbox Code Playgroud)
可以抢占,怎么能叫“原子”呢?
arm atomic inline-assembly linux-kernel load-link-store-conditional
我正在使用 Microsoft Visual Studio 2010,并且我正在尝试支持我的项目的 64 位构建。据我所知,64 位架构不支持 __asm 关键字。
以下是当项目仅支持 32 位构建时它的工作原理。
void*
Class1::Class2::operator new(size_t size)
{
void *pCaller;
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
char *pMem = (char *) malloc (sizeof(Class2) + size);
doSomething(pMem, pCaller);
void *ptr = (void *) (pMem + sizeof(Class2));
return(ptr);
}
Run Code Online (Sandbox Code Playgroud)
我可以使用预处理器指令使上述函数取决于建筑类型。
void*
Class1::Class2::operator new(size_t size)
{
#ifndef _WIN64
void *pCaller;
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
char *pMem = (char *) malloc (sizeof(Class2) + size);
doSomething(pMem, pCaller);
void *ptr …Run Code Online (Sandbox Code Playgroud) 我想在我的合约中包含一个内部方法,该方法允许在由参数命名的存储中创建一个新的 uint256。就像是:
function createUint (string memory _name) internal {
/*
* creates a new uint256 named _name in storage
*/
}
Run Code Online (Sandbox Code Playgroud)
我的猜测是它需要内联汇编,但我不知道如何
我正在研究基本的 shell 代码和orw代码。
但是,在此过程中,我收到以下错误消息:
错误:不支持的指令
mov
这是我的 C 和汇编代码框架:
// File name: orw.c
// Compile: gcc -o orw orw.c -masm=intel
__asm__(
".global run_sh\n"
"run_sh:\n"
"push 0x67\n"
"mov rax, 0x616c662f706d742f \n"
"push rax\n"
"mov rdi, rsp\n"
"xor rsi, rsi\n"
"xor rdx, rdx\n"
"xor eax, eax\n"
"mov eax, 2\n"
"syscall"
"\n"
"mov rdi, eax\n"
"mov rsi, rsp\n"
"sub rsi, 0x30\n"
"mov rdx, 0x30\n"
"xor eax, eax\n"
"syscall"
"\n"
"mov rdi,1\n"
"mov eax,1\n"
"syscall"
);
void run_sh();
int main() { run_sh(); …Run Code Online (Sandbox Code Playgroud) 我写了一个函数来漂亮地打印一个数独,当然这个模式可以由一些循环生成,但我不想经历麻烦,所以这就是我想出的(前 5 个格式说明符只是参数) printf 本身被压入堆栈,并且在回车后将被覆盖)。
\n虽然“它可以在我的机器上运行”,但我想知道这是否可以或可以移植到跨架构、编译器、libc 实现等工作?
\n当然,根据目标平台,汇编代码可能需要进行一些调整,并且 printf 推送的参数数量取决于当前的 libc 实现。
\n#define PUSH(x) asm volatile ("push %0" : : "m"(x) :)\n#define POP() asm volatile ("pop %%rax" : : : "rax")\n\nvoid print(void) {\n for (uint8_t i = 1; i <= (9 * 9); ++i) {\n PUSH(sudoku[(9 * 9) - i]);\n }\n\n printf("%hhd%hhd%hhd%hhd%hhd\\r\xe2\x95\x94\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x97\\n"\n "\xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91\\n"\n "\xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91 %hhd %hhd %hhd …Run Code Online (Sandbox Code Playgroud) 我正在使用 GNU arm-none-eabi 工具链为我的 Cortex M3 微控制器开发嵌入式 C 应用程序。
我计划采用供应商在我的 C 应用程序中实现的汇编子例程。我计划创建一个新的 C 函数,然后在其中使用扩展内联汇编协议编写内联汇编块。在这篇文章中,我计划将此汇编子例程视为黑匣子,并计划向此论坛询问如何构建输入和破坏列表;该例程没有输出。
汇编子例程期望在调用之前预先设置 r0、r1 和 r2。此外,子例程使用寄存器 r4、r5、r6、r7、r8、r9 作为临时寄存器来执行其功能。它写入设备上的一系列内存,由 r0 和 r1 指定,分别是起始地址和停止地址。
所以,我正在检查我的假设是否正确。我的问题如下。
void my_asm_ported_func(int reg_r0, int reg_r1, int reg_r2 {
__asm__ __volatile__ (
"ldr r0, %0 \n\t",
"ldr r1, %1 \n\t",
"ldr r2, %2 \n\t",
"<vendor code...> ",
: /* no outputs */
: "r" (reg_r0), "r" (reg_r1), "r" (reg_r2) /* inputs */
: "r0", "r1", "r2", "r4", "r5", "r6",
"r7", "r8", "r9", "memory" /* clobbers …Run Code Online (Sandbox Code Playgroud) 一些代码:
int x = 1;
for(int i = 1; i < 10; i++)
{
x *= i;
__asm {
mov eax, x
};
}
Run Code Online (Sandbox Code Playgroud)
如果这个程序用来eax增加值i,那么当我操作时会发生什么eax?
编译器是否会在__asm调用之前保存寄存器并在执行asm代码后使用它们,还是会忽略eax被操作并继续产生某种奇怪行为?
内部eax会发生什么?
编辑:即使我的代码只适用于Visual C++我想知道一般情况发生了什么以及不同的编译器将如何处理它.
inline-assembly ×10
assembly ×5
c ×4
c++ ×3
x86-64 ×3
arm ×2
gcc ×2
x86 ×2
arguments ×1
atomic ×1
att ×1
bare-metal ×1
cortex-m ×1
ethereum ×1
evm ×1
linux-kernel ×1
load-link-store-conditional ×1
optimization ×1
pintos ×1
porting ×1
solidity ×1
stack-memory ×1
visual-c++ ×1