我试图了解地址计算指令的工作原理,尤其是leaq命令.然后当我看到leaq用于进行算术运算的例子时,我感到困惑.例如,以下C代码,
long m12(long x) {
return x*12;
}
Run Code Online (Sandbox Code Playgroud)
在组装中
leaq (%rdi, %rdi, 2), %rax
salq $2, $rax
Run Code Online (Sandbox Code Playgroud)
如果我的理解是正确的,那么leaq应该移动任何(%rdi, %rdi, 2)应该2*%rdi+%rdi评估的地址%rax.我感到困惑的是,因为值x存储%rdi在内,这只是内存地址,为什么%rdi乘以3然后左移这个内存地址 2等于x乘以12?是不是当我们%rdi用3时,我们跳到另一个没有值x的内存地址?
如何使用最近的gcc(启用PIC)创建不可重定位的符号?我基本上想让以下C程序打印NULL:
#include <stdio.h>
extern int mem_;
int main(void) {
printf("%p\n", &mem_);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我试过的是一个小的汇编文件:
.data
.globl mem_
.type mem_,@object
.set mem_, 0
Run Code Online (Sandbox Code Playgroud)
但这会创建一个可重定位的符号,该符号在运行时不具有值0。
背景:我正在尝试运行一个旧程序,该程序使用此技巧直接从Fortran作为数组访问(分配)内存。由于该程序有“ 10”?LOC,重写所有内容是不可行的。
[编辑] GNU汇编器手册将“绝对部分”记录为
绝对部分:该部分的地址0始终“重定位”到运行时地址0。如果要引用的地址在重定位时ld不得更改,则此方法很有用。从这个意义上讲,我们说绝对地址是“无法重定位”的:它们在重定位期间不会改变。
这可能是我在这里需要的(对吗?),但是我找不到启用此部分的方法。该.struct指令记录为切换到“绝对部分”;但是以下汇编程序也不起作用:
.globl mem_
.struct 0
mem_:
Run Code Online (Sandbox Code Playgroud)
符号出现在此情况下,*ABS*有objdump:
$ objdump -t memc
memc: file format elf64-x86-64
[...]
0000000000000540 g F .text 000000000000002b _start
0000000000201030 g .bss 0000000000000000 __bss_start
000000000000064a g F .text 000000000000003c main
0000000000000000 g *ABS* 0000000000000000 mem_
[...]
Run Code Online (Sandbox Code Playgroud)
但它仍然被迁移。
我正在玩弄并试图了解计算机和程序的低级操作。为此,我正在尝试链接 Assembly 和 C。
我有2个程序文件:
“callee.c”中的一些C代码:
#include <unistd.h>
void my_c_func() {
write(1, "Hello, World!\n", 14);
return;
}
Run Code Online (Sandbox Code Playgroud)
我在“caller.asm”中还有一些 GAS x86_64 程序集:
.text
.globl my_entry_pt
my_entry_pt:
# call my c function
call my_c_func # this function has no parameters and no return data
# make the 'exit' system call
mov $60, %rax # set the syscall to the index of 'exit' (60)
mov $0, %rdi # set the single parameter, the exit code to 0 for normal exit
syscall
Run Code Online (Sandbox Code Playgroud)
我可以像这样构建和执行程序:
$ …Run Code Online (Sandbox Code Playgroud) 这应该是一个非常简单、非常快速的问题。这些是 CI 中编写的程序的前 3 行:
Dump of assembler code for function main:
0x0804844d <+0>: push ebp
0x0804844e <+1>: mov ebp,esp
0x08048450 <+3>: and esp,0xfffffff0
... ... ... ... ... ... ...
Run Code Online (Sandbox Code Playgroud)
什么是0x0804844d和?它不受 ASLR 的影响。它仍然是内存地址,还是文件的相对点?0x0804844e0x08048450
这是一个以前没有发生过的问题.我很确信这可能是我的包装回购的一个问题(我最近重新安装了我的Arch系统,而这刚刚开始发生).
我在x86_64中写了一个小小的hello世界:
.data
str: .asciz "Test"
.text
.globl main
main:
sub $8, %rsp
mov $str, %rdi
call puts
add $8, %rsp
ret
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用GCC进行汇编和链接 - 就像我过去做过很多次一样 - 简单地说:
gcc test.s -o test
然后输出此错误:
/ usr/bin/ld:/tmp/ccAKVV4D.o:在创建共享对象时,不能使用针对`.data'的重定位R_X86_64_32S; 使用-fPIC/usr/bin/ld重新编译:最终链接失败:输出collect2上的不可表示的部分:错误:ld返回1退出状态
这个错误从来没有发生在我身上.我试图通过谷歌搜索相同的错误消息解决问题,但它提出了具体的事情,而我认为这是一个普遍的问题.我已经尝试重新安装base-devel和整个GCC工具链.我不知道我还能做什么(请不要建议使用nasm,这是异端邪说).
我想我错过了一些明显的东西,但是我已经将GCC用于我的装配需求很长一段时间了.
我正在尝试使用 NASM 和 GCC 制作一个程序:
global main
extern puts
section .data
hi db 'hello', 0
section .text
main:
push hi
call puts
ret
Run Code Online (Sandbox Code Playgroud)
我正在构建:
nasm -f elf64 main.asm
gcc main.o -o main
rm main.o
Run Code Online (Sandbox Code Playgroud)
我得到:
/usr/bin/ld: main.o: relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
从像这样的示例中存在奇怪的堆栈操作来判断,我有一种感觉我做错了一些事情。不过,出于某种原因,我找不到任何实际解释这一点的文档(事实上,我几乎找不到任何使用 NASM 进行 64 位开发的有用文档,这使得我迄今为止所做的一切都成为真正的做起来很痛苦),并且添加类似的东西对我的错误输出没有任何影响。
更新:
我一直在看 …
给定寄存器中的数字(二进制整数),如何将其转换为十六进制ASCII数字字符串?
数字可以存储在存储器中或即时打印,但存储在存储器中并一次打印通常更有效.(您可以修改存储的循环,而不是一次打印一个循环.)
我们能否有效地处理与SIMD并行的所有半字节?(SSE2或更高版本?)
从我发现的所有文档中,没有提到像offset[var+offset2]Intel x86 语法那样的语法,但是 GCC 有以下标志
gcc -S hello.c -o - -masm=intel
对于这个程序
#include<stdio.h>
int main(){
char c = 'h';
putchar(c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
产生
.file "hello.c"
.intel_syntax noprefix
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
sub rsp, 16
mov BYTE PTR -1[rbp], 104
movsx eax, BYTE PTR -1[rbp]
mov edi, eax
call putchar@PLT
mov eax, 0
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size …Run Code Online (Sandbox Code Playgroud) 我有一个适用于Mac OS X的程序集hello world程序,如下所示:
global _main
section .text
_main:
mov rax, 0x2000004
mov rdi, 1
lea rsi, [rel msg]
mov rdx, msg.len
syscall
mov rax, 0x2000001
mov rdi, 0
syscall
section .data
msg: db "Hello, World!", 10
.len: equ $ - msg
Run Code Online (Sandbox Code Playgroud)
我想知道这条线lea rsi, [rel msg]。为什么NASM强迫我这样做?据我了解,它msg只是指向可执行文件中某些数据的指针,这样做mov rsi, msg会将地址放入rsi。但是,如果我将替换为lea rsi, [rel msg],则NASM会引发此错误(注意:我使用的是命令nasm -f macho64 hello.asm):
hello.asm:9: fatal: No section for index 2 offset 0 found
Run Code Online (Sandbox Code Playgroud)
为什么会这样?有什么特别之处lea是mov …
我有一条用Intel语法编写的指令(使用gas作为汇编程序),看起来像这样:
mov rdx, msg_size
...
msg: .ascii "Hello, world!\n"
.set msg_size, . - msg
Run Code Online (Sandbox Code Playgroud)
但是该mov指令正在汇编到mov 0xe,%rdx,而不是mov $0xe,%rdx我期望的那样。我应该如何编写第一条指令(或的定义msg_size)以获得预期的行为?