相关疑难解决方法(0)

理解C反汇编的电话

我想学习C调用约定.为此,我编写了以下代码:

#include <stdio.h>
#include <stdlib.h>

struct tstStruct
{
    void *sp;
    int k; 
};

void my_func(struct tstStruct*);

typedef struct tstStruct strc;

int main()
{
    char a;
    a = 'b';
    strc* t1 = (strc*) malloc(sizeof(strc));
    t1 -> sp = &a;
    t1 -> k = 40; 
    my_func(t1);
    return 0;   
}

void my_func(strc* s1)
{
        void* n = s1 -> sp + 121;
        int d = s1 -> k + 323;
}
Run Code Online (Sandbox Code Playgroud)

然后我使用GCC使用以下命令:

gcc -S test3.c
Run Code Online (Sandbox Code Playgroud)

并想出了它的装配.我不会显示我得到的整个代码,而是粘贴函数my_func的代码.就是这个:

my_func:
.LFB1:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16 …
Run Code Online (Sandbox Code Playgroud)

c assembly x86-64 calling-convention att

6
推荐指数
2
解决办法
6309
查看次数

在Assembly x86中将字符打印到标准输出

关于如何使用Assembly将字符打印到屏幕上我有点困惑.该架构是x86(linux).可以调用其中一个C函数还是有更简单的方法?我想输出的字符存储在寄存器中.

谢谢!

printing x86 assembly

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

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
查看次数

如何使用Linux内核模块中的Linux系统调用

我在Linux内核模块内调用系统调用时遇到一些困难.系统调用已经过测试,并且可以从标准的c用户空间程序中正常工作,但我似乎无法获得内核模块来编译和运行它们.

在我的用户程序中,我包含以下代码,系统调用有效:

#include <linux/unistd.h>   
#define __NR_sys_mycall 343

extern long int _syscall(long int_sysno,...)__THROW;

//and then a simple call is done as such
long value = syscall(__NR_sys_mycall);

printf("The value is %ld\n",value);
Run Code Online (Sandbox Code Playgroud)

但是当我在我的Linux内核模块中尝试相同的事情时,我得到了一堆错误,或者说错误:隐式声明函数'syscall'(如果我不包括_syscall定义)或一长串关于语法的错误if我...所以我的假设是我需要内核空间版本来调用系统调用.我是对还是错?

//My LKM code
#include <linux/module.h>
#include <linux/unistd.h>
#define __NR_sys_mycall 343

static int start_init(void)
{
   long value = syscall(__NR_sys_mycall);
   printk("The value is %ld\n",value);

   return 0;
}

static void finish_exit(void)
{
      printk("Done!\n");
}

module_init(start_init);
module_exit(finish_exit);
Run Code Online (Sandbox Code Playgroud)

c system-calls kernel-module linux-kernel

5
推荐指数
2
解决办法
5327
查看次数

为什么将变量`i`初始化为0和大尺寸会导致程序的大小相同?

有一个问题让我很困惑.

int main(int argc, char *argv[])
{
    int i = 12345678;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)
int main(int argc, char *argv[])
{
    int i = 0;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

尺寸

程序总共具有相同的字节.为什么?

那个字面值确实存储在哪里?文字段或其他地方?

记忆图

c variables size

5
推荐指数
2
解决办法
133
查看次数

NASM 和 8086 之间的区别

大家晚上好。我刚刚开始学习汇编语言,并且在网上找到了非常好的示例可以遵循。有人建议我使用 NASM 开始学习,但我发现的例子我看到他们使用 8086 汇编器。当我遵循这些示例时,我注意到如果我使用 NASM,它们不会在 Linux 终端上运行,但是如果我安装了 8086 汇编器模拟器,它确实可以工作。

我的问题是:NASM 和 8086 汇编器有什么区别吗?对我来说它们应该是同一件事,因为它是汇编代码。如果没有,有谁可以解释一下两者之间有什么区别吗?以及为什么它们不在 NASM 和 8086 上运行相同的代码

这是我跟踪的代码,它确实在 8086 汇编器上运行,但不在 Linux 上的 NASM 上运行

 DATA SEGMENT
     NUM1 DB ?
     NUM2 DB ?
     RESULT DB ?
     MSG1 DB 10,13,"ENTER FIRST NUMBER TO ADD : $"
     MSG2 DB 10,13,"ENTER SECOND NUMBER TO ADD : $"  
     MSG3 DB 10,13,"RESULT OF ADDITION IS : $"
ENDS
CODE SEGMENT 
    ASSUME DS:DATA CS:CODE
START:
      MOV AX,DATA
      MOV DS,AX

      LEA DX,MSG1
      MOV AH,9
      INT 21H

      MOV …
Run Code Online (Sandbox Code Playgroud)

x86 assembly nasm emu8086

5
推荐指数
0
解决办法
3280
查看次数

Mach-O 64位格式不支持32位绝对地址。NASM访问阵列

使用以下命令在我的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)

x86-64 mach-o nasm

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

MacOS 汇编的 64 位系统调用文档

我无法找到在 MacOS 上编写 64 位程序集的良好文档。

64位 SysV ABI在 A.2.1 节中说了以下内容,并且此 SO 帖子引用了它:

  • 系统调用是通过 syscall 指令完成的。内核销毁寄存器%rcx 和%r11。

  • 从系统调用返回,寄存器 %rax 包含系统调用的结果。-4095 到 -1 之间的值表示错误,它是 -errno。

这两句话在 Linux 上没问题,但在 macOS Sierra 上却是错误的,代码如下:

global _start
extern _exit

section .text
_start:

; Align stack to 16 bytes for libc
and rsp, 0xFFFFFFFFFFFFFFF0

; Call write
mov rdx, 12             ; size
mov rsi, hello          ; buf
mov edi, 1              ; fd
mov rax, 0x2000004      ; write ; replace to mov rax, 0x1 …
Run Code Online (Sandbox Code Playgroud)

macos assembly x86-64 system-calls abi

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

为什么系统调用会破坏 rcx 和 r11?

在《低级编程:英特尔® 64 位架构上的 C、汇编和程序执行》一书中它说:

关于系统调用参数 系统调用的参数与函数的参数存储在一组不同的寄存器中。第四个参数存储在 中r10,而函数接受第四个参数rcx

原因是syscall指令隐式使用rcx. 系统调用不能接受超过六个参数。

您可以在此Stack Overflow 帖子中也看到这一点,

系统调用是通过 syscall 指令完成的。这会破坏 %rcx 和 %r11,以及 %rax,但保留其他寄存器。

我理解 clobberingrax存储返回码,但为什么是rcx, 并且r11clobbered in syscall?是否有破坏rcx/的特定系统调用的列表r11?有没有关于破坏的约定?它们在任何系统调用中都被认为是安全的吗?

linux assembly x86-64 system-calls

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

通过值或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
查看次数