相关疑难解决方法(0)

如果在64位代码中使用32位int 0x80 Linux ABI会发生什么?

int 0x80在Linux上总是调用32位ABI,不管是什么模式,这就是所谓的:在args ebx,ecx...和系统调用号的/usr/include/asm/unistd_32.h.(或者在没有编译的64位内核上崩溃CONFIG_IA32_EMULATION).

64位代码应该使用syscall,从呼叫号码/usr/include/asm/unistd_64.h,并在args rdi,rsi等见什么调用约定UNIX和Linux系统上的i386和x86-64调用.如果您的问题被打上这样一个重复的,看你怎么说链接,细节应当使32位或64位代码的系统调用. 如果你想了解到底发生了什么,请继续阅读.


sys_write系统调用比syscall系统调用快,所以使用本机64位,int 0x80除非你正在编写多格式机器代码,当执行32或64位时运行相同的机器代码.(syscall始终以32位模式返回,因此它在64位用户空间中没有用,尽管它是有效的x86-64指令.)

相关:Linux系统的权威指南(在x86上)调用如何进行sysenterint 0x8032位系统调用,或sysenter64位系统调用,或调用vDSO进行"虚拟"系统调用syscall.加上有关系统调用的背景知识.


使用gettimeofday可以编写将以32位或64位模式组合的内容,因此它可以int 0x80在微基准测试结束时使用.

标准化函数和系统调用约定的官方i386和x86-64 System V psABI文档的当前PDF文件链接自https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI.

有关初学者指南,x86手册,官方文档和性能优化指南/资源,请参阅标记wiki.


但是,由于人们不断发布与使用代码的问题exit_group()在64位代码,或不小心建立64位二进制文件从源代码对于32位写的,我不知道是什么确切不会对当前的Linux怎样呢?

是否int 0x80保存/恢复所有的64位寄存器?它会将任何寄存器截断为32位吗?如果传递上半部分非零的指针args会发生什么?

如果你传递32位指针它是否有效?

linux assembly x86-64 system-calls abi

36
推荐指数
1
解决办法
4783
查看次数

程序集vim语法高亮

默认的汇编语法文件不能很好地工作并在网上搜索气体组件我没有发现任何关于vim的气体(AT&T)语法文件.有没有人发现这个?我无法编写自己的语法文件.

http://img168.imageshack.us/img168/46/nasm.png ft = nasm

http://img160.imageshack.us/img160/5857/asm.png ft = asm(默认)

http://img164.imageshack.us/img164/8476/tasm.png ft = tasm

vim x86 assembly vim-syntax-highlighting

27
推荐指数
3
解决办法
3万
查看次数

x86程序集pushl/popl不能与"错误:后缀或操作数无效"

我是汇编编程的新手,在GNU汇编程序v2.20.1的Ubuntu x86_64桌面上使用Programming Ground Up.

我已经能够组装/链接执行我的代码,直到我使用pushl/popl指令来操作堆栈.以下代码无法汇编:

 .section .data  # empty

 .section .text
.globl _start
_start:
 pushl $1       # push the value 1 onto the stack
 popl %eax      # pop 1 off the stack and into the %eax register
 int $0x80      # exit the program with exit code '1'
Run Code Online (Sandbox Code Playgroud)

使用"as test.s -o test.o",这些错误出现在终端上并且未创建test.o:

test.s: Assembler messages: 
test.s:9: Error: suffix or operands invalid for 'push'
test.s:10:  Error: suffix or operands invalid for 'popl'
Run Code Online (Sandbox Code Playgroud)

我检查了文档,我用于pushl和popl的操作数是有效的.这不是一个调试问题 - 所以我的代码出了什么问题?或者是我的汇编程序?

x86 assembly x86-64

27
推荐指数
3
解决办法
3万
查看次数

x86-64 Linux中不再允许32位绝对地址?

64位Linux默认使用小内存模型,它将所有代码和静态数据置于2GB地址限制之下.这可确保您可以使用32位绝对地址.较旧版本的gcc使用静态数组的32位绝对地址,以便为相对地址计算保存额外的指令.但是,这不再有效.如果我尝试在汇编中创建一个32位的绝对地址,我会收到链接器错误:"在创建共享对象时,不能使用".data"重定位R_X86_64_32S;使用-fPIC重新编译".当然,此错误消息具有误导性,因为我没有创建共享对象,-fPIC也没有帮助.到目前为止我发现的是:gcc版本4.8.5对静态数组使用32位绝对地址,gcc版本6.3.0不使用.版本5可能也没有.binutils 2.24中的链接器允许32位绝对地址,而2.28则不允许.

这种变化的后果是必须重新编译旧库并破坏传统汇编代码.

现在我想问一下:这个改变是什么时候做的?它在某处记录了吗?是否有一个链接器选项,使其接受32位绝对地址?

linux gcc x86-64 linker-errors relocation

21
推荐指数
1
解决办法
5787
查看次数

gcc可以编译x86程序集还是只链接它?

gcc可以生成程序集但是如何用gcc或其他编译器编译纯程序集?我知道x86汇编难,另一个指令集比MIPS和的Nios我一直在寻找,但现在我想尝试直接编译ASM 86.有关于如何操作的说明,但是包含了一个C文件,我不需要一个C文件用于我的第一个最基本的编译.

gcc -o test_asm asm_functions.S test_asm.c
Run Code Online (Sandbox Code Playgroud)

有创建.o文件的步骤

gcc -c asm_functions.S
gcc -c test_asm.c
gcc -o test_asm asm_functions.o test_asm.o
Run Code Online (Sandbox Code Playgroud)

但我没有看到我可以用gcc直接编译x86 asm的步骤.还有另一个名为GNU as(GNU Assembler)的程序,它可以用于将x86程序集转换为机器代码吗?

测试

代码(32.s)

.globl  _start

.text
_start:
        movl    $len, %edx
        movl    $msg, %ecx
        movl    $1, %ebx
        movl    $4, %eax
        int     $0x80

        movl    $0, %ebx
        movl    $1, %eax
        int     $0x80
.data
msg:
        .ascii  "Hello, world!\n"
        len =   . - msg
Run Code Online (Sandbox Code Playgroud)

脚步

$ gcc -c 32.s 
$ ls 32*
32.o  32.s
$ gcc -o 32 32.o 
32.o: In …
Run Code Online (Sandbox Code Playgroud)

compiler-construction x86 assembly gcc

20
推荐指数
1
解决办法
3万
查看次数

x86_64汇编Linux系统调用混淆

我目前正在学习Linux上的汇编语言.我一直在使用"从头开始编程"一书,所有的例子都是32位的.我的操作系统是64位,我一直在尝试以64位的方式完成所有示例.我遇到了麻烦:

.section .data

.section .text
.global _start
_start:
movq $60, %rax
movq $2, %rbx
int $0x80
Run Code Online (Sandbox Code Playgroud)

这只是调用Linux退出系统调用或它应该.相反,它会导致SEG FAULT,而当我改为执行此操作时

.section .data

.section .text
.global _start
_start:
movq $1, %rax
movq $2, %rbx
int $0x80
Run Code Online (Sandbox Code Playgroud)

有用.显然,问题是我转向%rax的价值.我在第二个例子中使用的$ 1值是"从头开始编程"所说的,但互联网上有多个来源说64位系统呼叫号码是60美元.参考 我做错了什么?还应该注意哪些其他问题以及我应该使用什么作为参考?万一你需要知道,我在第5章"从头开始编程".

64-bit assembly 32-bit gnu-assembler system-calls

16
推荐指数
4
解决办法
2万
查看次数

函数调用循环比空循环快

我将一些程序集与一些c链接起来测试函数调用的成本,使用以下程序集和c源代码(分别使用fasm和gcc)

部件:

format ELF

public no_call as "_no_call"
public normal_call as "_normal_call"

section '.text' executable

iter equ 100000000

no_call:
    mov ecx, iter
@@:
    push ecx
    pop ecx
    dec ecx
    cmp ecx, 0
    jne @b
    ret

normal_function:
    ret

normal_call:
    mov ecx, iter
@@:
    push ecx
    call normal_function
    pop ecx
    dec ecx
    cmp ecx, 0
    jne @b
    ret
Run Code Online (Sandbox Code Playgroud)

c来源:

#include <stdio.h>
#include <time.h>

extern int no_call();
extern int normal_call();

int main()
{
    clock_t ct1, ct2;

    ct1 = clock();
    no_call();
    ct2 = clock(); …
Run Code Online (Sandbox Code Playgroud)

c performance x86 assembly fasm

15
推荐指数
1
解决办法
969
查看次数

在64位Linux和64位处理器上运行32位汇编代码:解释异常

我遇到了一个有趣的问题.我忘了我正在使用64位机器和操作系统并写了一个32位汇编代码.我不知道如何编写64位代码.

这是Linux上Gnu Assembler(AT&T语法)的x86 32位汇编代码.

//hello.S
#include <asm/unistd.h>
#include <syscall.h>
#define STDOUT 1

.data
hellostr:
    .ascii "hello wolrd\n";
helloend:

.text
.globl _start

_start:
    movl $(SYS_write) , %eax  //ssize_t write(int fd, const void *buf, size_t count);
    movl $(STDOUT) , %ebx
    movl $hellostr , %ecx
    movl $(helloend-hellostr) , %edx
    int $0x80

    movl $(SYS_exit), %eax //void _exit(int status);
    xorl %ebx, %ebx
    int $0x80

    ret
Run Code Online (Sandbox Code Playgroud)

现在,这个代码应该在32位处理器和32位操作系统上正常运行吗?我们知道64位处理器向后兼容32位处理器.所以,这也不是问题.问题出现是因为64位操作系统和32位操作系统中的系统调用和调用机制不同.我不知道为什么但是他们改变了32位linux和64位linux之间的系统调用号码.

asm/unistd_32.h定义:

#define __NR_write        4
#define __NR_exit         1
Run Code Online (Sandbox Code Playgroud)

asm/unistd_64.h定义:

#define __NR_write              1
#define __NR_exit               60
Run Code Online (Sandbox Code Playgroud)

无论如何使用宏而不是直接数字都可以获得回报.它确保正确的系统呼叫号码.

当我组装和链接并运行程序时.

$cpp hello.S hello.s …
Run Code Online (Sandbox Code Playgroud)

linux x86 assembly gdb x86-64

14
推荐指数
2
解决办法
1万
查看次数

如何在不使用gcc的情况下将使用C标准库的气体组件程序与ld链接?

作为一个练习来更准确地学习c程序如何工作以及程序能够使用libc必须存在的最低内容级别,我自己尝试使用gas和ld主要在x86程序集中进行编程.

作为一个有趣的小挑战,我已成功组装并链接了几个链接到不同自制动态库的程序,但是我无法从头开始编写程序以使用libc函数调用而无需直接使用gcc.

我了解单个c库函数的调用约定,并通过使用objdump和readelf彻底检查了gcc编译的程序,但是在气体汇编文件中包含哪些信息以及要调用的参数方面没有任何进展在ld中成功链接到libc.有人对此有任何见解吗?

我在x86机器上运行Linux.

assembly gnu-assembler ld binutils

13
推荐指数
2
解决办法
8854
查看次数

在64位ubuntu上编译32位汇编程序

我有用32位汇编语言编写的程序......现在我无法在64位操作系统上编译它.在我们学校他们是具体的,程序必须用32位版本编写.这是我的计划:

bits 32
extern _printf
global _start

section .data
    message db "Hello world!!", 10, 0

section .text

_start:
    pushad 
    push dword message
    call _printf 
    add esp, 4 
    popad 
    ret
Run Code Online (Sandbox Code Playgroud)

任何的想法?我已经尝试了很多方法来编译它.编译后输出错误:

nasm -f elf64 vaja4.asm
ld vaja4.o -o vaja4
./vaja4
Run Code Online (Sandbox Code Playgroud)

输出:

vaja4.o: In function `_start':
vaja4.asm:(.text+0x7): undefined reference to `_printf'
Run Code Online (Sandbox Code Playgroud)

linux ubuntu 64-bit assembly 32-bit

12
推荐指数
2
解决办法
3万
查看次数