Относитесь к этому больше как к псевдокоду, чем к чему-либо. Если есть какой-то макрос или другой элемент, который, по вашему мнению, должен быть включен, дайте мне знать.
Я довольно новичок в сборке. Я программировал на фотопроцессоре еще в колледже, но с тех пор ничего.
Проблема здесь (ошибка сегментации) - первая инструкция после «Вход функции компиляции, кадр стека настройки». или "push% ebp". Вот что я узнал об этих двух инструкциях:
http://unixwiz.net/techtips/win32-callconv-asm.html
Сохраните и обновите% ebp:
Теперь, когда мы в новой функции, нам нужен новый фрейм локального стека, на который указывает% ebp, поэтому это делается путем сохранения текущего% ebp (который принадлежит фрейму предыдущей функции) и установки его в вершина стека.
push ebp
mov ebp, esp // ebp « esp
После изменения% ebp он теперь может напрямую ссылаться на аргументы функции как 8 (% ebp), 12 (% ebp). Обратите внимание, что 0 (% ebp) является старым указателем базы, а 4 (% ebp) является указателем старой инструкции.
Вот код. Это из JIT-компилятора для проекта, над которым я работаю. Я делаю это больше для обучения, чем для всего.
IL_CORE_COMPILE(avs_x86_compiler_compile)
{
X86GlobalData *gd = X86_GLOBALDATA(ctx);
ILInstruction *insn;
avs_debug(print("X86: Compiling started..."));
/* Initialize X86 Assembler opcode context */
x86_context_init(&gd->ctx, 4096, 1024*1024);
/* Compile function entrance, setup stack frame*/
x86_emit1(&gd->ctx, pushl, ebp);
x86_emit2(&gd->ctx, movl, esp, ebp);
/* Setup floating point rounding mode to integer truncation */
x86_emit2(&gd->ctx, subl, imm(8), esp);
x86_emit1(&gd->ctx, fstcw, disp(0, esp));
x86_emit2(&gd->ctx, movl, disp(0, esp), eax);
x86_emit2(&gd->ctx, orl, imm(0xc00), eax);
x86_emit2(&gd->ctx, movl, eax, disp(4, esp));
x86_emit1(&gd->ctx, fldcw, disp(4, esp));
for (insn=avs_il_tree_base(tree); insn != NULL; insn = insn->next) {
avs_debug(print("X86: Compiling instruction: %p", insn));
compile_opcode(gd, obj, insn);
}
/* Restore floating point rounding mode */
x86_emit1(&gd->ctx, fldcw, disp(0, esp));
x86_emit2(&gd->ctx, addl, imm(8), esp);
/* Cleanup stack frame */
x86_emit0(&gd->ctx, emms);
x86_emit0(&gd->ctx, leave);
x86_emit0(&gd->ctx, ret);
/* Link machine */
obj->run = (AvsRunnableExecuteCall) gd->ctx.buf;
return 0;
}
И когда вызывается obj-> run, он вызывается с obj в качестве единственного аргумента:
obj->run(obj);
Если это поможет, вот инструкции для всего вызова функции. Это в основном операция присваивания: foo=3*0.2;
. foo указывает на число с плавающей точкой в C.
0x8067990: push %ebp
0x8067991: mov %esp,%ebp
0x8067993: sub $0x8,%esp
0x8067999: fnstcw (%esp)
0x806799c: mov (%esp),%eax
0x806799f: or $0xc00,%eax
0x80679a4: mov %eax,0x4(%esp)
0x80679a8: fldcw 0x4(%esp)
0x80679ac: flds 0x806793c
0x80679b2: fsts 0x805f014
0x80679b8: fstps 0x8067954
0x80679be: fldcw (%esp)
0x80679c1: add $0x8,%esp
0x80679c7: emms
0x80679c9: leave
0x80679ca: ret
Редактировать: Как я уже говорил выше, в первой инструкции этой функции% ebp void. Это также инструкция, которая вызывает ошибку сегментации. Это потому что оно пустое или я ищу что-то еще?
Редактировать: поцарапать это. Я продолжаю набирать edp вместо ebp. Вот значения ebp и esp.
(gdb) print $esp
$1 = (void *) 0xbffff14c
(gdb) print $ebp
$3 = (void *) 0xbffff168
Редактировать: Эти значения выше неверны. Я должен был использовать команду 'x', как показано ниже:
(gdb) x/x $ebp
0xbffff168: 0xbffff188
(gdb) x/x $esp
0xbffff14c: 0x0804e481
Вот ответ от кого-то из списка рассылки по этому поводу. Кто-нибудь хочет осветить, что он имеет в виду немного? Как проверить, как настроен стек?
Непосредственная проблема, которую я вижу, заключается в том, что
указатель стека неправильно выровнен.
Это 32-битный код, а Intel
Руководство говорит, что стек должен быть
выровнен по 32-битным адресам. То есть,
наименее значимая цифра в esp
должно быть 0, 4, 8 или c.
Также отмечу, что значения в ebp и
ESP очень далеко друг от друга. Как правило,
они содержат похожие значения -
адреса где-то в стеке.
Я бы посмотрел, как был установлен стек
в этой программе.
Он ответил с исправлениями к вышеприведенным комментариям. Он не смог увидеть никаких проблем после дальнейшего ввода.
Другое редактирование: кто-то ответил, что кодовая страница не может быть помечена как исполняемая. Как я могу гарантировать, что он помечен как таковой?