2017-01-17 9 views
-2

При попытке сделать очень маленькую программу с NASM и GCC на моей машине Ubuntu, я заметил что-то странное.Разница между стеклом памяти i386 и x86-64

Следующий код компилируется нормально при 64-битном NASM и GCC:

global main 
    extern puts 

section .text 
    main: 
    push rax 
    mov rdi, message 
    call puts 
    jmp exit 
    exit: 
    ;return stack memory 
    pop rax 
    ret 
    message: 
    db "Hello from NASM!", 0 

Но при попытке компиляции тот же код (только регистры изменены) под 32-битной NASM и GCC, он будет либо дефект сегментации результата и/или случайные символы. Почему это происходит? Имеет ли архитектура x64 другой способ хранения памяти в стеке, чем i386? Если да, то как можно предотвратить это поведение?

+3

Вызывающие соглашения разные, не так ли? –

+0

Может быть, использовать отладчик и выяснить, где происходит ошибка? –

+0

Если на прошлой неделе они не изменили всю спецификацию языка, это не C, а язык ассемблера. Не спам-теги! (вызов функций библиотеки не меняет этого!) – Olaf

ответ

3

Когда в 32-битном режиме, наиболее соглашения о вызове (cdecl, stdcall, и т.д. ...) ожидают аргументы, которые будут в стек, а не в регистрах, в отличие от 64-битном режиме, а также, вам необходимо будет настроить указатель стека после вызова puts, так что вам нужно будет сделать что-то вроде:

lea edx, @message 
push edx 
call puts 
add esp, 4 

для программы, чтобы произвести тот же результат в 32-битном режиме. Возможно, у меня нет синтаксиса NASM, поскольку я обычно пишу код сборки в MASM и GAS.

+1

Так вот в чем проблема, спасибо! На самом деле я не сделал с i386 некоторое время. – Tatu

+1

На самом деле не имеет значения, что требуется для большинства * вызовов. Это стандартная функция библиотеки C, поэтому она будет использовать соглашение о вызове cdecl, что означает, что ваш ответ правильный. (Если это было stdcall, то вызываемый очистил бы стек, а не вызывающий!) –

+0

@CodyGray Согласен точно, но я пытался дать общий случай - если, скажем, он вызывал функцию, которая использовала ms fastcall вместо стандартной функции C, тогда было бы правильно иметь первый аргумент в ECX –

 Смежные вопросы

  • Нет связанных вопросов^_^