LINUX.ORG.RU

pusha, popa и AMD64


0

0

Пытаюсь скомпилировать одну программу, датированную 2003 годом. Программа содержит куски на ассемблере. Получаю серию ошибок:

Error: `pusha' is not supported in 64-bit mode

Error: `popa' is not supported in 64-bit mode

Вопрос: как обычно обходят такую проблему, на что эти команды заменяют?

В программе эти команды используются так:

В файлах на C:

__asm__("pusha;call _S_START;popa");

В файлах на ассемблере:

 pusha
 call _InvalidHWRead ; Display warning
 popa
...
 pusha
... ; много всяких mov и movzx с использованием 
... ; регистров eax, ax и al, другие регистры не используются
 popa

Вопрос явно не новый и давно многократно решённый, но я не нашёл конкретных рекомендаций. Пожалуйста, объясните, что писать, или ткните носом в соответствующий документ.

★★★★★
Ответ на: комментарий от linuxfan

> В гугле намертво забанен?

Нет, видимо запрос неверно формулировал.

> http://siyobik.info/index.php?module=x86&id=270

Спасибо. То есть pusha можно заменить следующей последовательностью:

mov Temporary, SP
push AX
push CX
push DX
push BX
push Temporary
push BP
push SI
push DI
А popa:
pop DI
pop SI
pop BP
pop Temporary
pop BX
pop CX
pop AX
mov SP, Temporary
Так?

А как задать переменную Temporary? Или можно её не задавать, а делать push SP последним в списке pusha, а pop SP первым в списке popa?

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

Сразу вопрос: как определить эти наборы команд в виде макросов? В C, наверное:

#define pusha_macro mov Temporary, SP; push AX; push CX; push DX; push BX; push Temporary; push BP; push SI; push DI;

А как в файлах ассемблера с интеловскоим синтаксисом?

question4 ★★★★★
() автор топика
Ответ на: комментарий от Booster

> push ax; push cx; push dx; push bx; push %sp;

Это понял. А почему только у sp знак % ? В программе на Си синтксис AT&T? тогда, наверное, нужно и остальным добавить .

add $10, 2(%esp)

А что даст эта команда? Почему не нужно сохранять bp, si и di?

Как на выходе проделать то же в обратном порядке? Так:

add $-10, 2(%esp); pop %sp; и т.д...

?

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

Сохранение регистров bp, si, di не написал. Знак % также не написал. Правильно так:

asm("push %ax; push %cx; push %dx; push %bx; push %sp; add $10, 2(%esp); push %bp; push %si, push %di");

Booster ★★
()
Ответ на: комментарий от question4

>add $10, 2(%esp) >А что даст эта команда?
Увеличивает на 10(размер пяти предыдущих push), область памяти sp+2.

И как её записать в формате Intel?

add word prt[sp+2], 10

Как на выходе проделать то же в обратном порядке?

В обратном порядке sp не используется, можно так:

asm(«pop %di; pop %si; pop %bp; pop %bx; pop %bx, pop %dx, pop %cx, pop %ax);

То есть два раза прочитать %bx.

Booster ★★
()
Ответ на: комментарий от question4

В вашем случае конечно будет:

 
add $10, 2(%sp)

Так как 16 бит код.

Для 32 соостветсвенно все константы умножаем на 2.

 
add $20, 4(%esp) 

P.S. Почему на лоре нет редактирования?

Booster ★★
()
Ответ на: комментарий от Booster

> P.S. Почему на лоре нет редактирования?

чтоб было видно всю дурость людей

anonymous
()
Ответ на: комментарий от question4

То есть pusha можно заменить следующей последовательностью:

mov Temporary, SP 
push AX 
push CX 
push DX 
push BX 
push Temporary 
push BP 
push SI 
push DI

Мне кажется подозрительным, что при портировании с 32bit на 64bit в программе появляются 16-битные инструкции. Кстати, а не должна ли эмуляция pusha сохранять ещё и регистры r8-r15?

const86 ★★★★★
()
Ответ на: комментарий от const86

> Мне кажется подозрительным, что при портировании с 32bit на 64bit в программе появляются 16-битные инструкции.

Не появляются, а были там с самого начала. Ассемблерная часть предназначена для обработки формата данных, разработанного ещё под 16-битный процессор :)

Кстати, а не должна ли эмуляция pusha сохранять ещё и регистры r8-r15?

Если в вызываемой функции нет обращений к r8-r15, меняется ли их содержимое и нужно ли его сохранять? По-моему, нет.

Заодно вопрос: нужно ли сохранять eax и rax, если функция работает с ax и al?

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

>А как задать переменную Temporary?

Никак, она не нужна. Сохрани все регистры, кроме SP, а потом восстанови — вот и все. ЕМНИП pushw %ax; pushw %bx; ...

linuxfan
()
Ответ на: комментарий от question4

сохраняй %rax/etc

А вообще выкини этот код на асме и напиши на Си.

anonymous
()
Ответ на: комментарий от question4

>Тогда «error: invalid effective address»
Да, 16 битная адресация ограничена. Если это не критично, то можно не сохранять sp, при загрузке он всё равно не используется.

Booster ★★
()
Ответ на: комментарий от Booster

> Да, 16 битная адресация ограничена. Если это не критично, то можно не сохранять sp, при загрузке он всё равно не используется.

загрузке чего?

anonymous
()
Ответ на: комментарий от Booster

Спасибо! Всё компилируется. Но не линкуется, пишет

i386 architecture of input file `S700.o' is incompatible with i386:x86-64 output
relocation R_X86_64_PC32 against symbol `_S_START' can not be used when making a shared object; recompile with -fPIC
final link failed: Bad value

Добавление в CFLAGS ключа -fPIC не помогает.

В чём дело, нужно сказать nasm-у компилировать S700.asm в 64-битный бинарник? Как это сделать?

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

> Ассемблерная часть предназначена для обработки формата данных, разработанного ещё под 16-битный процессор :)

Суровое развлечение, однако же...

Если в вызываемой функции нет обращений к r8-r15, меняется ли их содержимое и нужно ли его сохранять? По-моему, нет.

Если вызываемая функция не вызывает никаких других функций, которые чёрт знает что делают, то можно не сохранять.

Заодно вопрос: нужно ли сохранять eax и rax, если функция работает с ax и al?

Это всё один и тот же регистр. Можно сохранять rax для пущей надёжности, если нет уверенности, что ассемблерный код даже случайно не задевает старшие разряды регистров.

const86 ★★★★★
()
Ответ на: комментарий от true_admin

Как его слинковать с 64-битным GTK-1?

И вообще, как под Генту собирать 32-битные программы, чтобы работали? Без чрута и qemu.

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

> push/pop ecx/edx/eax

Intel® Extended Memory 64 Technology Software Developer’s Guide говорит, что так теперь нельзя. Либо 16 бит, либо 64. То есть заменить на push/pop rcx/rdx/rax

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

Слинкуй с 32-битным gtk.

Собирать можно в 32-битном чруте или погуглить как портежом собрать 32битные проги на amd64. Думаю, за чрут можно взять stage3.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

> погуглить как портежом собрать 32битные проги на amd64

Разработчики утверждают, что штатно — никак.

в 32-битном чруте

А без чрута?

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

собрать в чруте, потом пакет проинсталлить в основной системе вместе со всеми зависимостями. А можно собрать с каким-нить префиксом типа /usr/local/32/ чтобы не засорять систему.

true_admin ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.