Ошибка странного изменения ассемблера x86 GNU

Следующий ассемблерный код x86 прекрасно собирается, и раньше он работал без сбоев на linux-сервере моей школы, но при применении того же кода к моей виртуальной машине linux (ubuntu 14.04, внезапно это вызывает ошибку сегментации).

Изменились ли соглашения о стеке, это проблема с ассемблером GNU? Какую записку я пропустил? Я работаю на 64-битной машине, и это разогрев для создания основы ОС, поэтому мне нужно иметь возможность использовать 16-битный реальный, 32-битный защищенный и 64-битный режим все в одной программе. Итак, я полагаю, что мне действительно нужны маленькие детали о том, как сделать все режимы действительными в одной программе. Я знаю, что использовать .code16 / 32/64 при смене режимов, но я думаю, что мне не хватает (и я не могу найти ни в одном учебнике по ОС, как это сделать на 64-битной архитектуре.

.code32
.text 
.global _start

_start:

    pushl $str1
    pushl $len1
    call print
    addl $8, %esp <-cleans up the stack pointer

exit:

    movl $1, %eax
    movl $0, %ebx
    int $0x80

print:

    pushl %ebp
    movl %esp, %ebp

    movl $4, %eax
    movl $1, %ebx
    movl 12(%ebp), %ecx <- This is where the Seg Fault occurs according to GDB
    movl 8(%ebp), %edx
    int $0x80
    popl %ebp
    ret

.data

str1 : .ascii "String1\n"

len1 =  . - str1

Ответы на вопрос(1)

Ваш ответ на вопрос