GCC工具链默认使用AT&T汇编语法,但可通过该.intel_syntax指令获得对Intel语法的支持.
此外,AT和T以及英特尔语法都有a prefix和a noprefix版本,不同之处在于它们是否需要使用%sigil 为寄存器名称添加前缀.
根据存在的指令,地址常量的格式会发生变化.
我们考虑以下C代码
*(int *)0xdeadbeef = 0x1234;
Run Code Online (Sandbox Code Playgroud)
使用objdump -d,我们发现它被编译为以下汇编程序指令
movl $0x1234,0xdeadbeef
Run Code Online (Sandbox Code Playgroud)
由于没有涉及到寄存器,这对于正确的语法.att_syntax prefix和.att_syntax noprefix,即.嵌入在C代码中,它们看起来像这样
__asm__(".att_syntax prefix");
__asm__("movl $0x1234,0xdeadbeef");
__asm__(".att_syntax noprefix");
__asm__("movl $0x1234,0xdeadbeef");
Run Code Online (Sandbox Code Playgroud)
您可以选择用括号括起地址常量,即.
__asm__("movl $0x1234,(0xdeadbeef)");
Run Code Online (Sandbox Code Playgroud)
也会奏效.
将sigil添加到普通地址常量时,代码将无法复制
__asm__("movl $0x1234,$0xdeadbeef"); // won't compile
Run Code Online (Sandbox Code Playgroud)
当用paranthesis围绕这个表达式时,编译器将发出错误的代码而不发出警告,即
__asm__("movl $0x1234,($0xdeadbeef)"); // doesn't warn, but doesn't work!
Run Code Online (Sandbox Code Playgroud)
这将错误地发出指令
movl $0x1234,0x0
Run Code Online (Sandbox Code Playgroud)
在Intel模式下,PTR如果可能存在歧义,则地址常量必须以段寄存器为前缀,以及操作数大小和标志.在我的机器上(采用Windows XP和当前MinGW和Cygwin GCC版本的英特尔双核笔记本电脑),ds默认使用该寄存器.
常量周围的方括号是可选的.如果省略了段寄存器,但是括号存在,也可以正确识别地址常量.但是,忽略寄存器会在我的系统上发出警告.
在prefix模式中,段寄存器必须以前缀为前缀%,但仅使用括号仍然有效.这些是生成正确指令的不同方法:
__asm__(".intel_syntax noprefix");
__asm__("mov DWORD PTR ds:0xdeadbeef,0x1234");
__asm__("mov …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用内联汇编...我读过这个页面http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx但我无法理解传递给我的函数的参数.
我正在写一个C写的例子..这是我的函数头:
write2(char *str, int len){
}
Run Code Online (Sandbox Code Playgroud)
这是我的汇编代码:
global write2
write2:
push ebp
mov ebp, esp
mov eax, 4 ;sys_write
mov ebx, 1 ;stdout
mov ecx, [ebp+8] ;string pointer
mov edx, [ebp+12] ;string size
int 0x80 ;syscall
leave
ret
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能将代码传递给C函数...我正在做这样的事情:
write2(char *str, int len){
asm ( "movl 4, %%eax;"
"movl 1, %%ebx;"
"mov %1, %%ecx;"
//"mov %2, %%edx;"
"int 0x80;"
:
: "a" (str), "b" (len)
);
}
Run Code Online (Sandbox Code Playgroud)
那是因为我没有输出变量,所以我该如何处理呢?此外,使用此代码:
global main
main:
mov ebx, 5866 ;PID
mov ecx, …Run Code Online (Sandbox Code Playgroud) 当我尝试编译此代码时:
#include <stdio.h>
main(int argc, char *argv[]) {
double y = 0;
__asm__ ("fldl $150;"
"fsqrt;"
"fstl %0;" : : "g" (y) );
printf("%f\n", y);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
sqrt.c: Assembler messages:
sqrt.c:6: Error: suffix or operands invalid for `fld'
Run Code Online (Sandbox Code Playgroud)
为什么这不起作用?为什么我不能将数字"150"推入堆栈进行浮点运算?
我正在尝试为ia32编写GCC内联asm for CMPXCHG8B.不,我不能用__sync_bool_compare_and_swap.它必须使用和不使用-fPIC.
到目前为止,我所做的最好(编辑:毕竟不起作用,详见下面我自己的答案)
register int32 ebx_val asm("ebx")= set & 0xFFFFFFFF;
asm ("lock; cmpxchg8b %0;"
"setz %1;"
: "+m" (*a), "=q" (ret), "+A" (*cmp)
: "r" (ebx_val), "c" ((int32)(set >> 32))
: "flags")
Run Code Online (Sandbox Code Playgroud)
但是我不确定这实际上是否正确.
"b" ((int32)(set & 0xFFFFFFFF))由于PIC,我不能为ebx_val 做,但register asm("ebx")编译器接受了显然变量.
BONUS:ret变量用于分支,因此代码最终看起来像这样:
cmpxchg8b [edi];
setz cl;
cmp cl, 0;
je foo;
Run Code Online (Sandbox Code Playgroud)
任何想法如何描述输出操作数,使它成为:
cmpxchg8b [edi]
jz foo
Run Code Online (Sandbox Code Playgroud)
?
谢谢.
我想将C的outb函数移植到D.
static __inline void outb (unsigned char value, unsigned short int port)
{
__asm__ __volatile__ ("outb %b0,%w1"
:
:
"a" (value),
"Nd" (port));
}
Run Code Online (Sandbox Code Playgroud)
这是D版.
extern(C)
{
void outb (ubyte value, ushort port)
{
// I couldn't figure out this part
}
}
Run Code Online (Sandbox Code Playgroud)
这些是关于该主题的一些链接.
D内联汇编程序
GCC-内联汇编-HOWTO
http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
但我不懂汇编语言,所以我需要一些帮助.任何帮助,将不胜感激.谢谢.
我正在编写一个非常轻量级的libc替换库,以便我可以更好地理解内核 - 应用程序界面.第一项任务显然是使一些系统调用包装器到位.我已经成功地获得了1到3个参数包装器,但我正在努力使用4参数varient.这是我的出发点:
long _syscall4(long type, long a1, long a2, long a3, long a4)
{
long ret;
asm
(
"syscall"
: "=a"(ret)
: "a"(type), "D"(a1), "S"(a2), "d"(a3), "r10"(a4)
: "c", "r11"
);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
编译器给我以下错误:
error: matching constraint references invalid operand number
Run Code Online (Sandbox Code Playgroud)
我的_syscall3函数工作正常但不使用r10或有一个clobber列表.
有什么想法吗?
我的问题有些奇怪,但我会尽力解释.
看看linux内核的语言,我得到了C和汇编,即使我读了一篇文章说[引用] Unix的第二次迭代完全用C语言编写[/ quote]
我认为这是误导性的,但当我说内核有汇编代码时,我得到了两个问题
如果Linux内核真的完全用C语言编写,那么它是如何获得编译所需的GCC的呢?
我做了一个完整的find / -name *.s
,只是在/ usr/src/linux-headers- `uname -r/中的某处有一个汇编文件(asm-offset.s)
不知怎的,我不认为这有助于GCC的工作,那么linux如何在没有组装的情况下工作,或者如果它使用汇编它在哪里以及它如何在依赖于arch时稳定.
提前致谢
我正在尝试为GCC编写内联x86-64程序集以有效地使用MULQ指令.MULQ将64位寄存器RAX与另一个64位值相乘.另一个值可以是任何64位寄存器(甚至是RAX)或内存中的值.MULQ将产品的高64位放入RDX,将低64位放入RAX.
现在,很容易表达一个正确的mulq作为内联汇编:
#include <stdint.h>
static inline void mulq(uint64_t *high, uint64_t *low, uint64_t x, uint64_t y)
{
asm ("mulq %[y]"
: "=d" (*high), "=a" (*low)
: "a" (x), [y] "rm" (y)
);
}
Run Code Online (Sandbox Code Playgroud)
此代码是正确的,但不是最佳的.MULQ是可交换的,所以如果y恰好在RAX中,那么离开原点y并进行乘法是正确的.但GCC不知道这一点,因此会发出额外的指令将操作数移动到预先定义的位置.我想告诉GCC它可以将任一输入放在任一位置,只要一个在RAX中结束而MULQ引用另一个位置.GCC有一个这样的语法,称为"多个替代约束".注意逗号(但是整个asm()被破坏了;见下文):
asm ("mulq %[y]"
: "=d,d" (*high), "=a,a" (*low)
: "a,rm" (x), [y] "rm,a" (y)
);
Run Code Online (Sandbox Code Playgroud)
不幸的是,这是错误的.如果GCC选择第二个替代约束,它将发出"mulq%rax".要清楚,请考虑以下功能:
uint64_t f()
{
uint64_t high, low;
uint64_t rax;
asm("or %0,%0": "=a" (rax));
mulq(&high, &low, 7, rax);
return high;
}
Run Code Online (Sandbox Code Playgroud)
编译gcc -O3 -c -fkeep-inline-functions mulq.c,GCC发出这个程序集:
0000000000000010 …Run Code Online (Sandbox Code Playgroud) 我一直认为这是因为许多IDE和语法突出显示工具没有在C中突出显示ASM,但它们总是使用C++.内联汇编是否是C标准(ANSII或ISO)的一部分?
我想在测试夹具的测试中引起ARM Cortex-M3未定义指令异常.IAR编译器支持这种内联汇编,如下所示:
asm("udf.w#0");
不幸的是,GNU CC内联汇编程序不知道NXP LPC177x8x的这个操作码.它写诊断:
ccw3kZ46.s:404: Error: bad instruction `udf.w #0'
Run Code Online (Sandbox Code Playgroud)
如何创建导致未定义指令异常的函数?