LINUX.ORG.RU

nasm, стек, 64 бита

 , ,


1

3

Доброго времени суток. Не могу разобраться, подскажите пожалуйста. Если я хочу поместить в стек что либо отличное от 64 бит мне выдает ошибку когда я собираю программу. решил сделать по умному и записать 32 бита в eax, сдвинуть влево регистр rax на 32 бита, и положить еще раз в eax значение 32 бита. Но получается что когда я ложу в регистр eax значение старшая часть rax обнуляется. Пытался найти что либо в гугле, т.к. не я первый и не я последний кто с этим сталкивается, но не могу сформулировать нормально запрос чтобы найти что меня интересует. Подскажите в какую сторону копать, где что можно почитать чтобы найти ответы.

Код - то может покажешь?

И «ложат» знаешь что и куда?

Dennis7 ()
Последнее исправление: Dennis7 (всего исправлений: 1)

Эксперименты!

Век живи, век учись:

[luke@YavinIV LOR]$ cat test.s            
# AT&T syntax
# Add 3 and 2
.global _start

.text

_start: movq  $0x0123456789abcdef,%rax
        movl  $0x0000ffff,%eax
        movq  $0x0123456789abcdef,%rax
        movw  $0x00ff,%ax
        movq  $0x0123456789abcdef,%rax
        movb  $0x0f,%ah
        movq  $0x0123456789abcdef,%rax
        movb  $0x0f,%al

        movq  $1,%rax #halt programm
        int   $0x80 #call linux

[luke@YavinIV LOR]$ as test.s -g -o test.o
[luke@YavinIV LOR]$ ld test.o -g -o test  
[luke@YavinIV LOR]$ gdb ./test  
          
...

(gdb) b _start
Breakpoint 1 at 0x400078: file test.s, line 7.
(gdb) r
Starting program: /home/luke/asm/LOR/test 

Breakpoint 1, _start () at test.s:7
7	_start: movq  $0x0123456789abcdef,%rax
(gdb) si
8	        movl  $0x0000ffff,%eax
(gdb) p/x $rax
$1 = 0x123456789abcdef
(gdb) si
9	        movq  $0x0123456789abcdef,%rax
(gdb) p/x $rax
$2 = 0xffff
(gdb) si
10	        movw  $0x00ff,%ax
(gdb) p/x $rax
$3 = 0x123456789abcdef
(gdb) si
11	        movq  $0x0123456789abcdef,%rax
(gdb) p/x $rax
$4 = 0x123456789ab00ff
(gdb) si
12	        movb  $0x0f,%ah
(gdb) p/x $rax
$5 = 0x123456789abcdef
(gdb) si
13	        movq  $0x0123456789abcdef,%rax
(gdb) p/x $rax
$6 = 0x123456789ab0fef
(gdb) si
14	        movb  $0x0f,%al
(gdb) p/x $rax
$7 = 0x123456789abcdef
(gdb) si
16	        movq  $1,%rax #halt programm
(gdb) p/x $rax
$8 = 0x123456789abcd0f
(gdb) quit
A debugging session is active.

	Inferior 1 [process 21303] will be killed.

Quit anyway? (y or n) y

То есть для 32- и 16-битных команд сохраняется совместимость с i386, а вот логичной совместимости для 64 бит не наблюдается.

luke ★★★★★ ()
Последнее исправление: luke (всего исправлений: 1)

Поясню немного (хотя я это очень плохо делаю).

Для 16 и 32 битных x86 работает такая фича: если ты заполняешь сначала весь регистр, а потом только младшую половинку (или старшую), то старшая (или младшая соответственно) остаётся нетронутой.

Для amd64 архитектуры сохраняется совместимость только для тех команд, которые грубо говоря «не подозревают» о наличии старшего двойного слова у rax. Но при этом если заполнять младшее двойное слово этого регистра, то старшее стирается.

Вывод: надо читать спецификации по процессорам.

luke ★★★★★ ()
Ответ на: Эксперименты! от luke

логичной совместимости

Обнуление верхней части регистров уничтожает зависимости и облегчает работу перестановщика комманд процессора.

i-rinat ★★★★★ ()
Ответ на: комментарий от anonymous

Ещё раз. По теме скажешь что-нибудь, а не про системные вызовы?

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

Я так понимаю ТС интересовался не этим.

luke ★★★★★ ()

Максимум нубило.
Стек выравнивается по границе 16 байт.

старшая часть rax обнуляется.

МАКСИМУМ очевидно.

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