x86 内存访问分段错误 [英] x86 memory access segmentation fault

查看:15
本文介绍了x86 内存访问分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于好奇,我正在学习 x86 汇编.我目前正在使用带有 NASM 汇编器的基于 Linux 的操作系统.我很难理解为什么

I am learning x86 assembly out of curiosity. I'm currently using a Linux based OS with the NASM assembler. I am having a difficult time understanding why

SECTION .text

global _start

_start:

    nop
    mov ebx, 25
    mov [0xFFF], ebx

   ;Exit the program
   mov eax, 1
   mov ebx, 0
   int 0x80

会导致分段错误(将 ebx 寄存器的内容移动到内存位置 0xFFF 时).我在想用纯 asm 构建一个程序可以让我不受限制地访问我的进程的虚拟地址空间.不是这样吗?

Would lead to a segmentation fault (when moving the contents of the ebx register to memory location 0xFFF). I was thinking that building a program in pure asm would give me unrestricted access to my process' virtual address space. Is this not the case?

您将如何在汇编中实现诸如堆之类的东西?

How would you implement something like a heap in assembly?

推荐答案

在 Linux(x86) 上 - 尽管您的进程中有一个 4gb 的虚拟地址范围,但并不是所有的都可以访问.上面的 1gb 是内核所在的地方,有一些内存不足的区域不能使用.无法写入或读取虚拟内存地址 0xfff(默认情况下),因此您的程序会因段错误而崩溃.

On Linux(x86) - although you have a virtual address range of 4gb in your process, not all of it is accessible. The upper 1gb is where the kernel resides, and there are areas of low memory that can't be used. Virtual memory address 0xfff can't be written to or read from (by default) so your program crashes with a segfault.

在后续评论中,您建议您打算在汇编程序中创建一个堆.这可以做到,一种方法是使用 sys_brk 系统调用.它通过 int 0x80EAX=45 访问.它需要一个 EBX 中的指针来表示新的堆顶.通常,堆区域的底部被初始化为刚好超出程序数据段的区域(在内存中的程序上方).要获取初始堆位置的地址,您可以调用 sys_break 并将 EBX 设置为 0.系统调用后 EAX 将成为当前基址堆的指针.当您需要访问堆内存或分配更多堆空间时,可以将其保存起来.

In a followup comment you suggested you were intending to create a heap in assembler. That can be done, and one method is to use the sys_brk system call. It is accessed via int 0x80 and EAX=45 . It takes a pointer in EBX representing the new top of the heap. Generally the bottom of the heap area is initialized to the area just beyond your programs data segment(above your program in memory). To get the address of the initial heap location you can call sys_break with EBX set to 0. After the system call EAX will be the current base pointer of the heap. You can save that away when you need to access your heap memory or allocate more heap space.

为了清晰起见(而非性能),此代码提供了一个示例,但可能是了解如何操作堆区域的起点:

This code provides an example for purposes of clarity (not performance), but might be a starting point to understanding how you can manipulate the heap area:

SECTION .data
heap_base: dd 0          ; Memory address for base of our heap

SECTION .text
global _start
_start:
    ; Use `brk` syscall to get current memory address
    ; For the bottom of our heap This can be achieved
    ; by calling brk with an address (EBX) of 0
    mov eax, 45          ; brk system call
    xor ebx, ebx         ; don't request additional space, we just want to 
                         ; get the memory address for the base of our processes heap area.
    int 0x80
    mov [heap_base], eax ; Save the heap base

    ;Now allocate some space (8192 bytes)
    mov eax, 45          ; brk system call
    mov ebx, [heap_base] ; ebx = address for base of heap
    add ebx, 0x2000      ; increase heap by 8192 bytes
    int 0x80

    ; Example usage
    mov eax, [heap_base]      ; Get pointer to the heap's base
    mov dword [eax+0xFFF], 25 ; mov value 25 to DWORD at heapbase+0xFFF

    ;Exit the program
    mov eax, 1
    xor ebx, ebx
    int 0x80

这篇关于x86 内存访问分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆