gpt4 book ai didi

linux - NASM:两个后续文件写入不起作用

转载 作者:太空狗 更新时间:2023-10-29 11:03:33 30 4
gpt4 key购买 nike

尝试运行此代码以便我可以创建 bmp 文件 - 我写标题,然后我想将内容写入文件 - 一切都单独工作但不能一起工作。如果重要的话,我正在使用 hexedit 检查文件。

如果我运行带有标题编写部分的代码,它就可以工作。如果我运行带有内容编写部分的代码,它就可以工作。当我同时运行它们时却没有。

有什么想法吗?

代码如下:

section     .text
global _start

_start:

;#######################################################################
;### main ##############################################################
;#######################################################################

; open file
mov eax,8 ;system call number - open/create file
mov ebx,msg ;file name
mov ecx,111111111b ;file mode
int 0x80 ;call kernel

; save file descriptor to r8d
mov r8d, eax

; write headline to file
mov eax, 4 ;write 54 bytes to file
mov ebx, r8d ;load file desc
mov ecx, bmpheadline ;load adress of memory to write
mov edx, 54 ;load number of bytes
int 0x80 ;call kernel

; write content to file
mov eax, 4 ;number of syscall - write
mov ebx, r8d ;load file desc
;add ebx, 54 ;add 54 bytes to location of file location
mov ecx, empty_space ;load adress of buffer
mov edx, 40054 ;load number of bytes
int 0x80 ;call kernel

; close file
mov eax, 6 ;load syscall number - close
mov ebx, r8d ;load file desc
int 0x80 ;call kernel

; exit program
mov eax,1 ;syscall number - exit
int 0x80 ;call kernel

section .data

msg db 'filename.bmp',0x00 ;name of out file, 0x00 = end of string

bmpheadline db 0x42,0x4D,0xB6,0xDA,0x01,0x00,0x00,0x00,0x00,0x00,0x7A,0x00,0x00,0x00,0x6C,0x00,0x00,0x00,0xC9,0x00,0x00,0x00,0xC9,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x3C,0xDA,0x01,0x00,0x13,0x0B,0x00,0x00,0x13,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x47,0x52,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

section .bss

empty_space: resb 40054

最佳答案

您的代码有 2 个重大问题。 R8D (R8) 未在 int 0x80 中保留。其次,您原始问题中的 add ebx, 54 是不正确的。您不需要更改文件描述符。


64 位代码首选 SYSCALL

int 0x80 是 Linux 内核中的 IA32 兼容性功能。大多数 64 位 Linux 内核通常会启用此功能,但也可以将其关闭。您不能将 64 位指针与 int 0x80 一起使用。这可以防止使用基于堆栈的地址作为 int 0x80 的参数。出于这些原因,最好对 64 位程序使用 SYSCALL 而不是 int 0x80

有关在 Linux 中使用 SYSCALL 的更多信息,请参阅 Ryan Chapman's Blog .请注意,与 SYSCALL 一起使用的系统调用号与 int 0x80 不同。用于传递参数的寄存器不同,SYSCALL 中唯一不保留的寄存器是 RCXR11RAX(RAX 是返回值)。当前的 64-bit Linux System V ABI 中详细描述了系统调用约定。 .特别是:

  1. User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.
  2. A system-call is done via the syscall instruction. The kernel destroys registers %rcx and %r11.
  3. The number of the syscall has to be passed in register %rax.
  4. System-calls are limited to six arguments, no argument is passed directly on the stack.
  5. Returning from the syscall, register %rax contains the result of the system-call. A value in the range between -4095 and -1 indicates an error, it is -errno.
  6. Only values of class INTEGER or class MEMORY are passed to the kernel

如果您希望您的 64 位代码使用 INT 0x80

INT 0x80 在 64 位代码中有一些怪癖。它遵守保留 RBXRCXRDXRSI 的 32 位调用约定RDIRBP。对于其他 64 位寄存器,适用 64 位 C 调用约定。来自 ABI:

A.2.1 Calling Conventions

... applications that like to call system calls should use the functions from the C library. The interface between the C library and the Linux kernel is the same as for the user-level applications

参见上面链接的 64 位 Linux ABI 中的图 3.4:寄存器用法R12R13R14R15 也将被保留。

这意味着 RAXR8R9R10R11 不会被保留。将您的代码从使用 R8D 更改为保存的寄存器之一。 R12D 例如。


为什么你的代码会失败?

由于 R8D 未在 int 0x80 中保留,因此它可能被 SYS_WRITE 系统调用覆盖。第一个写入有效,第二个无效,因为 R8D 可能被第一个 SYS_WRITE 破坏,并且 R8D 可能成为无效的文件描述符.使用将被保留的寄存器之一应该可以解决这个问题。如果您用完了寄存器,您始终可以在堆栈上分配空间用于临时存储。

关于linux - NASM:两个后续文件写入不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40915909/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com