我正在尝试动态地将内存分配到堆中,然后在这些内存地址中分配值。我理解如何分配内存,但我如何将寄存器中的值分配给第一个动态内存地址? 这就是我到目前为止:`
push rbp
mov rbp, rsp ;initialize an empy stack to create activation records for the rest of the subroutines
mov rax, 0x2d ;linux system call for brk()
mov rbx, 0x0 ;to get the adress of the first adress we are allocating we must have 0 in rbx
int 0x80 ;calls the linux operating system kernel for assistance
mov [brk_firstLocation], rax ;the first position in the heap will be returned in rax thus i save the first loaction in a varable called brk_firstLocation
mov rbx, rax ;the memory adress of the start of the heap is moved in rbx
add rbx, 0x14 ;we want 5 bytes worth of data alocated in the heap, so the start adress plus 20 bits
mov rax, 0x2d ;linux system call for brk()
int 0x80 ;calls the linux operating system kernel for assistance
我做了什么,例如将rax中的值移动到brk_firstLocation
提前致谢!
答案 0 :(得分:3)
其他人已经指出了一些代码错误的问题。我想补充一点,你不会在当前断点上添加20个位(或者像add rbx, 20
实际上那样添加20个字节),你只需添加5个字节
另外,你的第一个系统调用参数不在rbx中,它将在rdi中。 The 64-bit syscall ABI使用不同的系统调用号,不同的寄存器和不同的指令(syscall
而不是int 0x80
),而不是32位ABI(在64位进程中仍然可用)。有关更多ABI链接,另请参阅x86标记wiki。
以下是您的代码的外观:
push rbp
mov rbp, rsp
;; sys_brk(0)
mov rax, 12 ; 12 is SYS_brk (/usr/include/asm/unistd_64.h)
mov rdi, 0 ; rdi for first syscall arg in the 64-bit ABI, not rbx
syscall ; syscall, not int 0x80, for the 64-bit ABI
mov qword [brk_firstLocation], rax
;; sys_brk(old_break + 5)
lea rdi, [rax + 5] ; add 5 bytes to the break point
mov rax, 12
syscall ; set the new breakpoint
此时,您可以使用brk_firstLocation作为指向要存储在堆上的任何5字节结构的指针。以下是将值放在该内存空间中的方法:
mov rdi, [brk_firstLocation] ; load the pointer from memory, if you didn't already have it in a register
mov byte [rdi], 'A' ; a char at it's first byte
mov [rdi+1], ecx ; a 32-bit value in the last 4 bytes.
答案 1 :(得分:2)
int 80h
仅适用于32位系统调用。请改为使用syscall
代替64位。
两次调用sys_brk是多余的 - 在汇编中,您始终知道程序数据的结束位置。只需在那里贴上标签即可获得地址。
以这种方式分配内存少于一页是没有意义的,无论如何它将以4KB的块分配。
重要的是要理解 - sys_brk不是堆管理功能。它是低级别的内存管理。
答案 2 :(得分:1)
我看到了很多问题:
所以你想要这样的东西:
mov [brk_firstloaction], _end
mov rbx, [brk_firstlocation]
add rbx, 0x14 ; space for 5 dwords (20 bytes)
mov rax, 12
int 0x80
答案 3 :(得分:0)
正如您所做的那样,调用一次以检索堆的当前底部,然后移动堆的顶部(这是brk值)。但是,使用64位寄存器集r.x
时,您的代码不正确。如果您的Linux是32位(如系统调用号使用45所暗示的那样),那么您需要32位寄存器集:
mov eax, 45 ; brk
mov ebx, 0 ; arg 1: 0 = fail returning brk value in rax
int 0x80 ; syscall
mov dword ptr [brk_firstLocation], rax ; save result
mov eax, 45 ; brk
mov ebx, 4 ; arg 1: allocate 4 bytes for a 32-bit int
int 0x80 ; syscall
mov eax, dword ptr [brk_firstLocation] ; reload rax with allocated memory address.
mov dword ptr [eax], 42 ; use result: store 42 in newly allocated storage
当然,您可以根据需要重新加载保存的值以便重复使用。