我想得到一个变量的地址和4096(它对应于其内存页面的地址).由于这是可以离线计算的东西,我做了一些看起来像这样的事情(v是变量,vpage应该包含其页面的地址):
.data
v: .zero 0x100
vpage: .long v & 0xfffff000
Run Code Online (Sandbox Code Playgroud)
尝试使用x86汇编程序编译此文件会导致以下错误:
test.S: Assembler messages:
test.S:3: Error: invalid sections for operation on `v' and `L0'
Run Code Online (Sandbox Code Playgroud)
为什么GAS拒绝计算这个?现在奇怪的部分:用"+"替换'&',代码将编译,链接后甚至可以正确计算地址.任何有关此行为原因或如何解决此问题的提示都将非常受欢迎.
我实际上是在学习装配,我和Gas一起去了,但问题是:
1)我只知道英特尔语法,我在一个页面中看到,在某些情况下,具有intel语法的Gas不是很好.这是正确还是我错了?我在谈论这个网站:
2)然后我也看到(我不记得页面)事实气体可以在几个架构中组装也减慢了组装的程序.这样对吗?
3)你推荐哪种汇编程序可以产生高度优化的代码?我在其他问题中看到,在某些情况下,每个汇编程序都可以转换为不同的操作码.我在YASM,FASM,GAS和NASM之间,但其他推荐被接受.知道FASM非常快......
非常感谢!保持这个伟大的社区!
我在GCC有一个场景给我带来了问题.我得到的行为不是我期望的行为.总结一下这种情况,我提出了一些x86-64的新指令,它们是在硬件模拟器中实现的.为了测试这些指令,我正在使用现有的C源代码并使用十六进制对新指令进行手动编码.因为这些指令与现有的x86-64寄存器交互,所以我使用input/output/clobber列表来声明GCC的依赖关系.
发生的事情是,如果我调用一个函数,例如printf,则不会保存和恢复相关寄存器.
例如
register unsigned long r9 asm ("r9") = 101;
printf("foo %s\n", "bar");
asm volatile (".byte 0x00, 0x00, 0x00, 0x00" : /* no output */ : "q" (r9) );
Run Code Online (Sandbox Code Playgroud)
101被分配给r9,内联汇编(本例中为假)依赖于r9.这在没有printf的情况下正确运行,但是当它存在时,GCC不会保存和恢复r9,并且在调用自定义指令时会有另一个值.
我想也许GCC可能秘密地将赋值更改为变量 r9,但是当我这样做时
asm volatile (".byte %0" : /* no output */ : "q" (r9) );
Run Code Online (Sandbox Code Playgroud)
看看汇编输出,确实使用的是%r9.
我正在使用gcc 4.4.5.您认为可能会发生什么?我认为GCC将始终在函数调用中保存和恢复寄存器.有什么方法可以强制执行吗?
谢谢!
编辑:顺便说一句,我正在编译这样的程序
gcc -static -m64 -mmmx -msse -msse2 -O0 test.c -o test
Run Code Online (Sandbox Code Playgroud) 我在Xcode(4.5.2)中有一个使用Debug配置构建的项目.但是,现在我已经切换到构建Release配置,我遇到了一个问题:我的一个内联汇编函数正在收到错误Invalid symbol redefinition.谷歌搜索该错误消息发现我有一些人有编译器错误,但没有关于它意味着什么的信息.这是函数,带有注释的错误行:
inline int MulDivAdd(int nNumber,
int nNumerator,
int nDenominator,
int nToAdd)
{
int nRet;
__asm__ __volatile__ (
"mov %4, %%ecx \n"
"mov %1, %%eax \n"
"mull %2 \n"
"cmp $0, %%ecx \n"
"jl __sub \n"
"addl %%ecx, %%eax \n"
"adc $0, %%edx \n"
"jmp __div \n"
"__sub: \n" // "Invalid symbol redefinition"
"neg %%ecx \n"
"subl %%ecx, %%eax \n"
"sbb $0, %%edx \n"
"__div: \n" // "Invalid symbol redefinition"
"divl %3 \n"
"mov %%eax, %0 \n" …Run Code Online (Sandbox Code Playgroud) 我需要一些帮助来理解GCC为什么这么做
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp # ???
subl $48, %esp # ???
movl $8, 16(%esp)
movl $4, 20(%esp)
Run Code Online (Sandbox Code Playgroud)
为什么先减去16再减去48呢?这样做会不容易subl $64, %esp?
作为一个具体的例子,在GAS 2.24上移动地址:
mov $s, %eax
s:
Run Code Online (Sandbox Code Playgroud)
后:
as --64 -o a.o a.S
objdump -Sr a.o
Run Code Online (Sandbox Code Playgroud)
使用零扩展:
0000000000000000 <s-0x5>:
0: b8 00 00 00 00 mov $0x0,%eax
1: R_X86_64_32 .text+0x5
Run Code Online (Sandbox Code Playgroud)
但内存访问:
mov s, %eax
s:
Run Code Online (Sandbox Code Playgroud)
编译以签署扩展名:
0000000000000000 <s-0x7>:
0: 8b 04 25 00 00 00 00 mov 0x0,%eax
3: R_X86_64_32S .text+0x7
Run Code Online (Sandbox Code Playgroud)
在这种特定情况下,或者一般情况下,是否有理由使用?我不明白汇编程序如何能够对任何一种情况做出更好的假设.
NASM 2.10.09仅R_X86_64_32用于上述两种情况.更新:在2.11之后的一个边缘nasm commit 6377180产生相同的Gas输出,这看起来像Ross提到的一个bug.
我已经解释了我认为我理解的内容R_X86_64_32S:https://stackoverflow.com/a/33289761/895245
我正在阅读RISC-V测试模式的源代码.在riscv-test.h中有一个宏定义,
我想知道1:这段代码意味着什么:
#define RVTEST_CODE_BEGIN \
.section .text.init; \
.align 6; \
.weak stvec_handler; \
.weak mtvec_handler; \
.globl _start; \
_start: \
/* reset vector */ \
j reset_vector; \
.align 2; \
trap_vector: \
/* test whether the test came from pass/fail */ \
csrr t5, mcause; \
li t6, CAUSE_USER_ECALL; \
beq t5, t6, write_tohost; \
li t6, CAUSE_SUPERVISOR_ECALL; \
beq t5, t6, write_tohost; \
li t6, CAUSE_MACHINE_ECALL; \
beq t5, t6, write_tohost; \
/* if …Run Code Online (Sandbox Code Playgroud) 要在多个函数中定义相同的本地标签:
.text
.globl main
func:
push %rbp
mov %rsp, %rbp
.a:
leave
ret
main:
push %rbp
mov %rsp, %rbp
.a:
leave
ret
Run Code Online (Sandbox Code Playgroud)
奇怪地得到错误:
$ clang -c main.s
main.s:13:1: error: invalid symbol redefinition
.a:
^
Run Code Online (Sandbox Code Playgroud)
当我使用yasm时,它允许多个功能使用相同的本地标签。你有什么线索吗?
我正在重新学习我在很老的MS-DOS机器上使用的汇编程序!
这是我对该功能应该是什么样的理解.它编译但崩溃了SIGSEGV试图把时0xffffffff在ecx.
代码在具有32位Debian 9的VM中运行.任何帮助将不胜感激.
int getStringLength(const char *pStr){
int len = 0;
char *Ptr = pStr;
__asm__ (
"movl %1, %%edi\n\t"
"xor %%al, %%al\n\t"
"movl 0xffffffff, %%ecx\n\t"
"repne scasb\n\t"
"subl %%ecx,%%eax\n\t"
"movl %%eax,%0"
:"=r" (len) /*Output*/
:"r"(len) /*Input*/
:"%eax" /*Clobbered register*/
);
return len;
}
Run Code Online (Sandbox Code Playgroud) 我在x86机器上有以下绝对间接跳转指令:
ff 24 25 30 10 60 00
产生于:
jmp *bar
但是我在解码它的第二个和第三个字节时遇到了麻烦。
第二个应该是Mod R / M字段。因此它翻译为:
00 100 100
含义:
00 -没有位移的内存(但是它具有恒定的地址,这不是“位移”吗?)
100(12月4日)-扩展操作。代码(FF / 4 => JMP r / m32)
100-?? SIB?但是该指令中没有使用寄存器
PS一些上下文:
Breakpoint 4, test () at test.s:13
13 jmp *bar
(gdb) disassemble /r
Dump of assembler code for function test:
0x000000000040051b <+0>: c7 04 25 30 10 60 00 2f 05 40 00 movl $0x40052f,0x601030
=> 0x0000000000400526 <+11>: ff 24 25 30 10 60 00 jmpq …Run Code Online (Sandbox Code Playgroud)