相关疑难解决方法(0)

如果我要在程序集中编写程序,那么这个HelloWorld汇编代码的哪些部分是必不可少的?

我有这个简短的你好世界计划:

#include <stdio.h>

static const char* msg = "Hello world";

int main(){
    printf("%s\n", msg);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用gcc将它编译成以下汇编代码:

    .file   "hello_world.c"
    .section    .rodata
.LC0:
    .string "Hello world"
    .data
    .align 4
    .type   msg, @object
    .size   msg, 4
msg:
    .long   .LC0
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    movl    msg, %eax
    movl    %eax, (%esp)
    call    puts
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa …
Run Code Online (Sandbox Code Playgroud)

c linux x86 assembly

10
推荐指数
1
解决办法
1149
查看次数

系统调用如何在Linux上实际发生?

灵感来自这个问题

如何强制GDB反汇编?

并与此相关

什么是INT 21h?

如何在Linux下实际发生系统调用?执行调用时会发生什么,直到调用实际的内核例程?

linux internals system-calls linux-kernel

9
推荐指数
2
解决办法
2404
查看次数

在64位系统上组装32位二进制文​​件(GNU工具链)

我编写了可以编译的汇编代码:

as power.s -o power.o
Run Code Online (Sandbox Code Playgroud)

当我链接power.o目标文件时出现问题:

ld power.o -o power
Run Code Online (Sandbox Code Playgroud)

为了在64位操作系统(Ubuntu 14.04)上运行,我.code32power.s文件的开头添加了,但是我仍然得到错误:

分段故障(核心转储)

power.s:

.code32
.section .data
.section .text
.global _start
_start:
pushl $3
pushl $2 
call power 
addl $8, %esp
pushl %eax 

pushl $2
pushl $5
call power
addl $8, %esp

popl %ebx
addl %eax, %ebx

movl $1, %eax
int $0x80



.type power, @function
power:
pushl %ebp  
movl %esp, %ebp 
subl $4, %esp 
movl 8(%ebp), %ebx 
movl 12(%ebp), %ecx 
movl %ebx, -4(%ebp) 

power_loop_start:
cmpl …
Run Code Online (Sandbox Code Playgroud)

linux x86 assembly build att

9
推荐指数
2
解决办法
3853
查看次数

最快的Linux系统调用

在支持的英特尔x86-64的系统syscallsysret什么是从64位用户代码"最快"的系统调用在香草内核?

特别是,它必须是一个系统调用来执行syscall/ sysretuser < - >内核转换1,但除此之外的工作量最少.它甚至不需要进行系统调用本身:某种类型的早期错误从未调度到内核端的特定调用,这是好的,只要它不会因为这样而走慢路径.

这样的调用可用于估计原始syscallsysret开销,而与呼叫完成的任何工作无关.


1特别是,这排除了似乎是系统调用但在VDSO中实现的内容(例如,clock_gettime)或由运行时缓存(例如getpid).

linux performance x86-64 microbenchmark

8
推荐指数
2
解决办法
1464
查看次数

重定位 R_X86_64_32 针对 `.data' 不能在创建共享对象时使用;

我写了下面的汇编代码,它可以直接通过as和ld构建pass。

as cpuid.s -o cpuid.o
ld cpuid.o -o cpuid
Run Code Online (Sandbox Code Playgroud)

但是当我使用gcc来完成整个过程时。我遇到以下错误。

$ gcc cpuid.s -o cpuid
/tmp/cctNMsIU.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o:(.text+0x0): first defined here
/usr/bin/ld: /tmp/cctNMsIU.o: relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/usr/bin/ld: final link failed: Invalid operation
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

然后我将 _start 修改为 main,并将 -fPIC 添加到 gcc 参数。但这并不能解决我的 ld 错误。错误消息更改为以下。

$ gcc …
Run Code Online (Sandbox Code Playgroud)

c assembly ld

8
推荐指数
1
解决办法
7348
查看次数

近和远JMP

我正在进行Linux汇编,我知道它有一个平坦的内存模型.令我困惑的是NEAR和FAR JMP.

NEAR属于同一部分,而FAR是另一部分.据我所知,linux虚拟内存中没有任何段?另外我们如何知道我的程序代码是否分布在多个部分中?

x86 assembly nasm

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

为什么x86-64 Linux系统调用可以使用6个寄存器?

我正在用C编写一个独立程序,它只依赖于Linux内核.

我研究了相关手册 ,得知X86-64上的Linux系统调用入口点接收通过七个寄存器的系统调用号和六个参数rax,rdi,rsi,rdx,r10,r8,和r9.

这是否意味着 每个系统调用都接受六个参数?

我研究了几个libc实现的源代码,以了解它们如何执行系统调用.有趣的是,musl包含两种不同的系统调用方法:

  1. src/internal/x86_64/syscall.s

    此汇编源文件定义了一个__syscall函数,该函数将系统调用号和正好六个参数移动到ABI中定义的寄存器.该函数的通用名称暗示它可以与任何系统调用一起使用,尽管它总是将六个参数传递给内核.

  2. arch/x86_64/syscall_arch.h

    此C头文件定义了七个单独的__syscallN函数,并N指定了它们的arity.这表明只传递系统调用所需的确切数量的参数的好处超过了拥有和维护七个几乎相同的函数的成本.

所以我自己尝试了一下:

long
system_call(long number,
            long _1, long _2, long _3, long _4, long _5, long _6)
{
    long value;

    register long r10 __asm__ ("r10") = _4;
    register long r8  __asm__ ("r8")  = _5;
    register long …
Run Code Online (Sandbox Code Playgroud)

operating-system x86-64 system-calls abi linux-kernel

7
推荐指数
1
解决办法
833
查看次数

mmap Mac:分段错误

我的Mac上的以下内容成功:

int main() {
    int* addr = (int*) mmap(0, 100, 1 | 2, 2 | 4096, -1, 0);

    *addr = 25;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是下面的代码是相同的,但是当我尝试*addr使用分段错误写入时失败:

int main() {
    int* addr = (int*) syscall(SYS_mmap, 0, 100, 1 | 2, 2 | 4096, -1, 0);

    *addr = 25;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

syscall成功返回一个内存地址,但当我尝试写入它时失败.

我这样编译:

g++ ./c++/mmap.cc -o ./mmap && ./mmap
Run Code Online (Sandbox Code Playgroud)

如果我运行两个版本dtruss:

g++ ./c++/mmap.cc -o ./mmap && sudo dtruss ./mmap
Run Code Online (Sandbox Code Playgroud)

然后两个版本都成功了,我看到两个版本的相同mmap调用:

mmap(0x0, 0x64, 0x3, 0x1002, 0xFFFFFFFF, …
Run Code Online (Sandbox Code Playgroud)

c c++ system-calls

7
推荐指数
1
解决办法
248
查看次数

ptrace 能否判断 x86 系统调用使用的是 64 位还是 32 位 ABI?

我正在尝试使用 ptrace 来跟踪由单独进程发出的所有系统调用,无论是 32 位 (IA-32) 还是 64 位 (x86-64)。我的跟踪器将在启用 IA-32 仿真的 64 位 x86 安装上运行,但理想情况下能够跟踪 64 位和 32 位应用程序,包括 64 位应用程序是否分叉并执行 32 位进程.

问题是,由于 32 位和 64 位系统调用号不同,我需要知道进程是 32 位还是 64 位以确定它使用哪个系统调用,即使我有系统调用号。似乎有不完美的方法,例如检查/proc/<pid>/exec或(如 strace 那样)寄存器结构的大小,但没有什么可靠的。

更复杂的是,64 位进程可以从长模式切换到直接执行 32 位代码。他们还可以进行 32 位int $0x80系统调用,当然,使用 32 位系统调用号。我不“相信”我跟踪的进程不会使用这些技巧,所以我想正确检测它们。而且我已经独立验证,至少在后一种情况下,ptrace 看到的是 32 位系统调用号和参数寄存器分配,而不是 64 位的。

我在内核源代码中找到了 中的TS_COMPAT标志arch/x86/include/asm/processor.h,每当 64 位进程进行 32 位系统调用时,该标志似乎都会设置。唯一的问题是我不知道如何从用户空间访问这个标志,或者是否有可能。

我还考虑过阅读%cs并将其与$0x23or进行比较$0x33,受到这种在运行过程中切换位数的 …

linux x86 ptrace x86-64 system-calls

7
推荐指数
1
解决办法
845
查看次数

Linux x86-64 系统调用何时破坏 %r8、%r9 和 %r10?

我刚刚浏览了Linux内核源代码树并阅读了文件tools/include/nolibc/nolibc.h

syscall在这个文件中看到了 use %r8%r9以及%r10在 clobber 列表中。
还有一条评论说:

rcx 和 r8..r11 可能会被破坏,其他的则被保留。

据我所知,syscall只有 clobbers%rax%rcx%r11和记忆)。

有没有syscall真实%r8的例子%r9%r10

linux assembly x86-64 system-calls

7
推荐指数
1
解决办法
1036
查看次数