如果我编译这个程序:
#include <stdio.h>
int main(int argc, char** argv) {
printf("hello world!\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于x86-64,asm输出使用movl $.LC0, %edi/ call puts.(请参阅godbolt上的完整asm输出/编译选项.)
我的问题是:GCC如何知道字符串的地址可以适合32位立即数操作数?为什么不需要使用movabs $.LC0, %rdi(即a mov r64, imm64,不是零或符号扩展imm32).
AFAIK,没有任何迹象表明加载器必须决定在任何特定地址加载数据部分.如果字符串存储在上面的某个地址,1ULL << 32那么movl将忽略更高的位.我对clang有类似的行为,所以我不认为这是GCC独有的.
我关心的原因是我想创建自己的数据段,它存在于我选择的任意地址(可能超过2 ^ 32)的内存中.
当我使用 gcc 编译 print.s 时,出现以下错误:
/usr/bin/ld: /tmp/cc45uyZj.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)
我在另一个 linux 发行版中尝试了同样的方法,它运行得很好。
添加-fPIC没有帮助。apt-get 更新也不行。
如果你想看代码:https : //github.com/NEGU93/Compilation.git里面的练习 > Part1。当然是文件print.s(顺便说一句。当我做gcc时,所有的.s文件都有类似的错误)。
我想 Kali 发行版中缺少某些东西,但我不知道它可能是什么。
使用以下命令在我的Mac计算机上运行此代码:
nasm -f macho64 -o max.a maximum.asm
Run Code Online (Sandbox Code Playgroud)
这是我尝试在计算机上运行的代码,该代码在数组中找到最大的数字。
section .data
data_items:
dd 3,67,34,222,45,75,54,34,44,33,22,11,66,0
section .text
global _start
_start:
mov edi, 0
mov eax, [data_items + edi*4]
mov ebx, eax
start_loop:
cmp eax, 0
je loop_exit
inc edi
mov eax, [data_items + edi*4]
cmp eax, ebx
jle start_loop
mov ebx, eax
jmp start_loop
loop_exit:
mov eax, 1
int 0x80
Run Code Online (Sandbox Code Playgroud)
错误:
maximum.asm:14: error: Mach-O 64-bit format does not support 32-bit absolute addresses
maximum.asm:21: error: Mach-O 64-bit format does not support 32-bit absolute …Run Code Online (Sandbox Code Playgroud) 我正在尝试将一些高性能的汇编函数编写为练习,并且遇到了在运行程序时发生的奇怪的段错误,但在valgrind或nemiver中却没有.
基本上一个不应该运行的cmov,带有一个越界的地址,即使条件总是假的,也会让我发生段错误
我有一个快速和慢速的版本.缓慢的一直在工作.快速的一个工作,除非它收到一个非ascii字符,此时它崩溃可怕,除非我在adb或nemiver上运行.
ascii_flags只是一个128字节的数组(最后有一点空间),包含所有ASCII字符(alpha,numeric,printable等)的标志
这工作:
ft_isprint:
xor EAX, EAX ; empty EAX
test EDI, ~127 ; check for non-ascii (>127) input
jnz .error
mov EAX, [rel ascii_flags + EDI] ; load ascii table if input fits
and EAX, 0b00001000 ; get specific bit
.error:
ret
Run Code Online (Sandbox Code Playgroud)
但这不是:
ft_isprint:
xor EAX, EAX ; empty EAX
test EDI, ~127 ; check for non-ascii (>127) input
cmovz EAX, [rel ascii_flags + EDI] ; load ascii table if input fits
and EAX, flag_print ; get …Run Code Online (Sandbox Code Playgroud) 我想知道如何在Intel语法的某些指令中将标签名称与寄存器名称区分开。例如,call rdx通常意味着间接跳转,但是如果我们rdx在同一程序集文件中有标签怎么办?我认为可以将其解释为直接跳转到rdx。是否有任何符号告诉汇编器是哪个?
我正在用 AT&T 语法使用 Assembly x86(32 位)为大学编写一个项目。在课程中,我们使用 gnu Gas 和命令 ld 编译了源文件。现在我正在使用 GCC,因为我想创建一个汇编函数并从 C 程序调用它。
但是当我开始使用 GCC 进行编译时,我收到了这些关于链接和重定位的奇怪警告。
/usr/bin/ld: obj/telemetry.o: warning: relocation in read-only section `.text'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
Run Code Online (Sandbox Code Playgroud)
这是导致警告的文件的一个小示例。仅当我尝试访问/使用 .data 中声明的静态变量时才会发生警告
.file "telemetry.s"
.data
test: .string "Example"
.text
.globl telemetry
.type telemetry, @function
telemetry:
pushl %ebp
movl %esp, %ebp
pushl %ebx
leal test, %ebx # if i comment this line warnings wont happen
popl %ebx
popl %ebp
ret
Run Code Online (Sandbox Code Playgroud)
我仅在 Ubuntu 22.04.01 上使用当前使用的 gcc 版本 (11.2.0) 时收到警告。这是命令: …
我试图了解小代码模型中使用的 RIP 相对偏移量。也许互联网上有关此主题的唯一可用资源是: https: //eli.thegreenplace.net/2012/01/03/understanding-the-x64-code-models 但在这篇文章中也有一些事情不清楚。我使用这个简单的程序来了解一些事情:
// sample.cc
int arr[10] = {0};
int arr_big[100000] = {0};
int arr2[500] = {0};
int main() {
int t = 0;
t += arr[7];
t +=arr_big[6];
t += arr2[10];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
汇编:g++ -c sample.cc -o sample.o
.text 部分的目标代码:( objdump -dS sample.o)
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
b: 8b 05 00 …Run Code Online (Sandbox Code Playgroud) 是否rax得到偏移加上该指令的地址,或下一个?从微码的角度来看,如果答案是下一条指令可能会更容易.
我试图了解地址计算指令的工作原理,尤其是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)
但它仍然被迁移。