【问题标题】:NASM malloc returns NULLNASM malloc 返回 NULL
【发布时间】:2015-06-14 06:26:00
【问题描述】:

在我尝试学习 NASM 的过程中,我尝试创建一个基本程序来测试 malloc 的功能。我已经贴在下面了:

bits 64

extern malloc

section .data

ARRAY_SIZE:             equ 27

array:                  dq 1

error_message:          db "Malloc returned NULL!", 10
error_message_length:   equ $ - error_message

section .text
global _start

_start:
    ; try to allocate an array of bytes in the heap memory using malloc
    push dword ARRAY_SIZE
    call malloc
    ;; if malloc returned NULL, throw an error
    cmp rax, 0
    je err_out
    mov [array], eax                ; save a pointer to the allocated memory in array

    ; fill the array with numbers equal to the indices at that location
    fill_for:
    xor edx, edx                    ; use edx for the for loop index
    .for_start:
    cmp edx, ARRAY_SIZE             ; break if edx >= BUFFER_SIZE
    jg .for_end
        mov [array + edx], edx      ; array[i] = i;
    inc edx
    .for_end:

    ; print the numbers in array
    print_for:
    xor edx, edx                    ; use edx for the for loop index
    .for_start:
    cmp edx, ARRAY_SIZE             ; break if edx >= BUFFER_SIZE
    jg .for_end
        mov eax, [array + edx]      ; print array[i]
        call print_small_number
    .for_end:

print_small_number:
; allocate stack space for the two-digit number string (two digit chars + '\0' = 3b)
;; save the old rbp
mov [rbp], rsp
sub rsp, 8
mov rbp, rsp
;; allocate space for the number string
sub rsp, 3
;; save rdx for the main function
sub rsp, 8
mov [rbp + 3], rdx

    ; turn the (assumed two-digit in base 10) number into a string in number_string
    ;; initialize the number to 0x30, 0x30, 0 (0x30 is the offset to turn a number into a base-10 digit; 10 = '\n')
    mov byte [rbp], 0x30
    mov byte [rbp + 1], 0x30
    mov byte [rbp + 2], 10
                                    ; the number to print is already in eax
    mov bl, 10                      ; divide the message length string by 10 to separate the 10s and 1s digits
    div bl                          ;; the quotient is the 10s digits and the remainder is the 1s
    add [rbp], al                   ; move the resulting char into the first slot in number_string
    add [rbp + 1], ah               ; move the resulting 1s digit char into the second slot in number_string

    ; print the message length string
    mov eax, 4
    mov ebx, 1
    mov rcx, rbp                    ; the string starts at rbp
    mov edx, 3                      ; two digits + \0 = 3 chars = 3b
    int 0x80

; return
;; restore the old rdx for the main function
mov rdx, [rbp + 3]
add rsp, 8
;; deallocate the number string
add rsp, 3
;; restore the old rbp
add rsp, 8
mov rbp, [rsp]
ret

err_out:
    ; print error_message
    mov eax, 4
    mov ebx, 1
    mov ecx, error_message
    mov edx, error_message_length
    int 0x80

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

但是,当我从这个基本的 NASM 程序调用 malloc 时,它返回 NULL (0),显示为打印出以下消息:

Malloc returned NULL!

我在一台 6GB RAM 的笔记本电脑上运行这个程序,几乎没有其他应用程序打开,我只尝试分配 27 个字节,所以内存不足似乎不太可能。

我知道如果给定的 size 参数为负数,它可能会返回 NULL,但正如您在代码中看到的那样,情况并非如此。

有人有什么建议吗?我不明白为什么这个 malloc 调用会返回 NULL。

编辑:

这个示例是在 64 位 Linux Mint 17 Qiana 中组装和运行的,使用以下命令(自 BASH 脚本起):

nasm -f elf64 "$1.asm" -l "$1.lst" &&
ld -s -o "$1" "$1.o" -lc &&
./"$1"

【问题讨论】:

    标签: malloc nasm heap-memory dynamic-memory-allocation


    【解决方案1】:

    malloc() 的参数应该进入rdi,而不是被压入堆栈。它可能失败了,因为您传递了 0 或某个极高的数字。

    还有:

    mov [array], eax
    

    应该是:

    mov array, rax
    

    因为malloc() 非常有能力返回一个不适合四个字节的地址,并且因为array 在那个时候不包含有效的内存地址,所以你不应该间接通过它。

    【讨论】:

    • x86_64 程序集使用与 x86 程序集完全不同的调用约定。虽然 x86 调用中的所有参数都被压入堆栈,但所有 x86_64 参数都放置在寄存器中。 (RDI, RSI, RDX, RCX, R8, and R9,按此顺序)
    • 前六个整数参数是,至少,至少绝大多数时间都是它们。
    • 哦,我明白了。我试过了,它似乎已经修复了它。这就解释了为什么我看到的所有示例都使用了堆栈。然后,我想知道,如果你有一个接受超过 6 个参数的函数,在 x86_64 汇编中会发生什么?
    • @REALDrummer:剩下的整数参数然后通过堆栈传递。
    • 调用约定继续,但我没有将它提交到内存中。 (谢谢保罗,我只是想查一下)
    猜你喜欢
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    相关资源
    最近更新 更多