相关疑难解决方法(0)

Linux x86_64 汇编套接字编程

大家好。

所以我正在学习汇编。
按照我通常学习的任何新语言的学习步骤,我已经到达了使用程序集的网络。

遗憾的是,情况不太好,因为我在第 0 步几乎失败了,这将获得一个可以开始通信的套接字。

汇编代码应大致等于以下 C 代码:

#include <stdio.h>
#include <sys/socket.h>

int main(){
        int sock;
        sock = socket(AF_INET, SOCK_STREAM, 0);
}
Run Code Online (Sandbox Code Playgroud)

(让我们忽略它现在没有关闭套接字的事实。)

所以这是我到目前为止所做的:

  • 检查了手册。这意味着我需要做一个socketcall()这一切都很好。问题开始于它需要一个int描述它应该进行什么样的套接字调用的。调用手册对此也没有多大帮助,因为它仅描述了以下内容:

在某些架构上——例如 x86-64 和 ARM——没有 socketcall() 系统调用;相反,socket(2)、accept(2)、bind(2) 等实际上是作为单独的系统调用实现的。

  • 然而,在系统调用的原始列表中没有这样的调用——据我所知socket()accept()bind()listen()、 等是来自libnet而不是来自内核的调用。这让我很困惑,所以我决定编译上面的C代码并使用strace. 这产生了以下结果:

    套接字(PF_INET,SOCK_STREAM,IPPROTO_IP)= 3

  • 虽然这并没有让我更接近于知道它是什么socket() 但它确实解释了它的论点。对于女巫,我似乎没有找到合适的文档(再次)。我认为PF_INETSOCK_STREAMIPPROTO_IP就在被定义<sys/socket.h>,但我grep似乎对他们-ing没有发现使用的东西。所以我决定通过gdbdisass main查找值一起使用来实现它。这给出了以下输出:

    汇编代码转储功能主要:0x00000000004004fd …

c sockets linux assembly x86-64

5
推荐指数
1
解决办法
8216
查看次数

通过值或C中的struct的多个参数

让我们假设这个结构:

typedef struct mytest_t {
    uint8_t field1;
    uint32_t field2;
    uint64_t field3;
    uint64_t field4;
    uint16_t field5;
    uint32_t field6;

} mytest_t;
Run Code Online (Sandbox Code Playgroud)

还有一些想要创建此结构的函数(有点像一个对象):

int something_with(uint8_t field1, uint32_t field2, uint64_t field3, uint16_t field5) {
    mytest_t *object = malloc(sizeof(mytest_t));

    object->field1 = field1;
    object->field2 = field2;
    object->field3 = field3;
    object->field4 = 0x12345678;
    object->field5 = field5;
    object->field6 = 42;

    dosomethingwith(object);
    return 0;
}

void initial() {
    something_with(123, 456, 789, 456);
}
Run Code Online (Sandbox Code Playgroud)

这些功能纯粹是出于我的情况。此函数就像一个帮助程序,在代码中有一个单一的点,在该点上,对象被填充然后转发到其他对象。

注意:这个例子很小,假设参数要长2到3倍。

为了避免将大量参数传递给函数,并使调用变得冗长且难以阅读,我考虑将一个预填充的mytest_t结构作为参数传递(假设需要的字段正确填充)。

将struct作为值或指针传递会更好吗?取消引用所有字段的成本是多少?既然所有内容都在堆栈中,那有什么区别吗?编译器可以某种方式对其进行优化吗?

void initial() {
    mytest_t source = {
        .field1 = 123, …
Run Code Online (Sandbox Code Playgroud)

c stack struct pointers micro-optimization

5
推荐指数
1
解决办法
170
查看次数

x86_64 Linux系统调用参数

我正在Linux上学习x86_64程序集,我遇到了一些我希望可以解决的冲突信息.一方面,我已经读过,对于syscall参数,你会按照rdi,rsi,rdx等顺序使用寄存器.但另一方面,我读过你使用寄存器rbx,rcx,rdx等.一个人告诉我,这是因为ABI的原因,但我并不完全明白这究竟意味着什么.

所以我想我要问的是,为什么这两种格式和哪种格式适合使用?

谢谢!

x86-64 system-calls

4
推荐指数
1
解决办法
1447
查看次数

为什么x86-64 Linux系统调用会修改RCX,值是什么意思?

我正在尝试使用sys_brksyscall 在Linux中分配一些内存。这是我尝试过的:

BYTES_TO_ALLOCATE equ 0x08

section .text
    global _start

_start:
    mov rax, 12
    mov rdi, BYTES_TO_ALLOCATE
    syscall

    mov rax, 60
    syscall
Run Code Online (Sandbox Code Playgroud)

事情是按照linux调用约定,我希望返回值在rax寄存器中(指向已分配内存的指针)。我在gdb中运行了此文件,并在进行了sys_brksyscall 后注意到以下寄存器内容

在系统调用之前

rax            0xc      12
rbx            0x0      0
rcx            0x0      0
rdx            0x0      0
rsi            0x0      0
rdi            0x8      8
Run Code Online (Sandbox Code Playgroud)

系统调用后

rax            0x401000 4198400
rbx            0x0      0
rcx            0x40008c 4194444 ; <---- What does this value mean?
rdx            0x0      0
rsi            0x0      0
rdi            0x8      8
Run Code Online (Sandbox Code Playgroud)

rcx在这种情况下,我不太了解寄存器中的值。哪个指针可以用作我分配给它的8个字节的开头的指针sys_brk

linux assembly x86-64 system-calls

4
推荐指数
1
解决办法
1229
查看次数

NASM 我应该在调用函数后弹出函数参数吗?

假设我有一个像这样的 nasm 函数:

inc:
    mov rax,[rsp + 8]
    add [rax],BYTE 1
    ret
Run Code Online (Sandbox Code Playgroud)

我这样调用这个函数:

push some_var
call inc
Run Code Online (Sandbox Code Playgroud)

我想通过堆栈将参数传递给函数,因此我压入some_var然后调用我的函数。在函数中,我的项目位于堆栈中的第二个,因此我将其视为:mov rax,[rsp+8]

我的问题是:调用函数后我应该以某种方式从堆栈中弹出我的参数吗?如果是这样,我可以以某种方式从堆栈中删除它,我的意思是弹出它,但不注册?(因为我不再需要这个论点了。)

更新:我发现我可以简单地add rsp,8从堆栈中删除项目。但这是好的做法吗?调用函数后从堆栈中删除参数?

assembly callstack x86-64 nasm calling-convention

4
推荐指数
1
解决办法
1212
查看次数

x64 参数和返回值调用约定

我调用 Clang 12.0.0 来-Os -march=haswell编译以下 C 程序:

int bar(int);

int foo(int x) {
  const int b = bar(x);
  if (x || b) {
      return 123;
  }
  return 456;
}
Run Code Online (Sandbox Code Playgroud)

生成以下程序集:

foo:                                    # @foo
        push    rbx
        mov     ebx, edi
        call    bar
        or      eax, ebx
        mov     ecx, 456
        mov     eax, 123
        cmove   eax, ecx
        pop     rbx
        ret
Run Code Online (Sandbox Code Playgroud)

https://gcc.godbolt.org/z/WsGoM56Ez

据我了解,foo 的调用者在 RAX/EAX 中设置了 x。然后 foo 调用 bar,这不需要修改 RAX/EAX,因为 x 是作为未修改的输入传递的。

or eax, ebx指令似乎是将输入 x 与 bar 的结果进行比较。该结果如何最终进入 EBX?有何目的mov …

c assembly x86-64 calling-convention

4
推荐指数
1
解决办法
1552
查看次数

NASM中断x86参考?

我似乎找不到关于 Linux 系统上 NASM x86 中断的好参考。例如,它是什么int 0x60以及它与什么不同int 0x80

是否有手册列出了可以与int指令结合使用的所有中断号?

x86 nasm system-calls x86-16

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

int 0x80是否会覆盖寄存器值?

我编写了一个程序,它应该像for循环一样,打印一串文本一定次数.

这是代码:

global _start


    section .data

    msg db "Hello World!",10    ; define the message
    msgl equ $ - msg            ; define message length
                                ; use minimal size of storage space

    imax dd 0x00001000          ; defines imax to be big!

    section .text
_start:


    mov r8, 0x10          ; <s> put imax in r8d, this will be our 'i' </s>
                          ; just attempt 10 iterations
_loop_entry:                    ; loop entry point
    mov eax, 4                  ; setup the message to print
    mov ebx, …
Run Code Online (Sandbox Code Playgroud)

linux 64-bit assembly gdb nasm

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

GCC 内联程序集错误:“'int' 的操作数大小不匹配”

首先,如果有人知道标准 C 库的一个函数,该函数无需查找二进制零即可打印字符串,但需要绘制字符数,请告诉我!

否则,我有这个问题:

void printStringWithLength(char *str_ptr, int n_chars){

asm("mov 4, %rax");//Function number (write)
asm("mov 1, %rbx");//File descriptor (stdout)
asm("mov $str_ptr, %rcx");
asm("mov $n_chars, %rdx");
asm("int 0x80");
return;

}
Run Code Online (Sandbox Code Playgroud)

GCC 将以下错误告知“int”指令:

"Error: operand size mismatch for 'int'"
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我这个问题吗?

c assembly gcc x86-64 inline-assembly

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

是否有不同 x86_64 操作和 C std lib 函数使用的寄存器列表?

我开始在 ubuntu linux 上使用 NASM 汇编器学习 x86_64 汇编编程。我遇到的问题之一是弄清楚操作神奇地使用了哪些寄存器。

我正在阅读的书有这样的代码示例:

mov    rdi, fmt1
mov    rsi, strng
mov    rax, 0
call   printf

; How am I supposed to know which registers are used by the call to printf? 
; The libc printf function supports an arbitrary number of parameters. 
; Clearly there aren't an unlimited number of registers in x86_64 so how does this work
; as the parameter list grows?
Run Code Online (Sandbox Code Playgroud)

代码示例的另一部分是这样的:

xor    rax, rax
mov    rbx, strng
mov    rcx, strLen
mov …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 nasm calling-convention

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