2016-10-28 10 views
0

У меня есть следующий код. Может кто-нибудь объяснить мне вопросы в скобках?Понимание Y86

# Execution begins at address 0 (why?) 
.pos 0 
irmovq stack, %rsp # Set up stack pointer (how can i move the word "stack" in rsp) 
call main # Execute main program 
halt # Terminate program 

# Sample linked list (what is the purpose of .align 8?) 
.align 8 
ele1: 
.quad 0x00a 
.quad ele2 
ele2: 
.quad 0x0b0 
.quad ele3 
ele3: 
.quad 0xc00 
.quad 0 

main: 
irmovq ele1,%rdi 
call sum 
ret 


sum: 


# Stack starts here and grows to lower addresses 
.pos 0x100 
stack: 

ответ

1

Выполнение начинается 0, потому что это то, что делает .pos 0 на следующей строке.

Слово «стопка» не перемещается: stack это метка далее в коде, которая устанавливает указатель стека rsp в это место в памяти.

Назначение выравнивания по 8-байтовым границам состоит в том, что процессор не принимает любезно для перекрытия такой границы. В директиве .quad генерируются 8-байтовые данные.

Это не тема, чтобы попросить учебные пособия - это очень легко для Google, и вы идете с тем, который вам кажется правильным.

+0

I думаю, что у вас может быть причина и следствие, смешанные в вашем первом предложении, то есть '.pos 0' был использован, потому что выполнение начинается с' 0'. Начальное местоположение, будь то конкретный адрес памяти или определенный символ, продиктовано базовой платформой, а не тем, кто или что-либо пишет код. – 8bittree

2

.pos <adr> Директива об изменении текущего виртуального адреса для компилятора. Таким образом, следующая инструкция, скомпилированная, будет рассмотрена по адресу <adr>, если вы поставите перед ней <label>, то <label> будет иметь значение <adr>, поэтому любая инструкция позже в коде, работающем с абсолютным адресом <label>, будет скомпилирована с <adr> значением.

Также компилятор отслеживает текущий виртуальный адрес во время компиляции, поэтому, если вы используете несколько инструкций позже, оно будет иметь значение <adr + size_of_produced_machine_code_so_far>.

Когда вы загружаете машинный код в этом положении в реальной памяти, все абсолютные адреса в коде будут соответствовать и работать корректно (если вы загрузите его в другом месте, это будет работать неправильно, так как инструкции все равно будут отображаться к <adr>, для которого они были скомпилированы).

В вашем примере это означает, что первый irmovq, как ожидается, будет размещен по адресу 0, как только этот машинный код загрузится в компьютер с памятью.

Почему выполнение начинается с адреса 0? Кто знает, это особенность целевой платформы. Если целевая платформа начнет выполняться с 0x300, имеет смысл вместо этого ввести код запуска, с директивой .pos 0x300.


irmovq stack, %rsp # Set up stack pointer (how can i move the word "stack" in rsp)

rsp устанавливается, чтобы содержать адрес stack символа (на самом деле это значение «стек» символ, который можно рассматривать как адрес памяти в человеческой логики, но это просто номер, как все в компьютере), что составляет 0x100 значение (из-за .pos директива прямо перед этим stack: определение метки). Так что инструкция rsp = 0x100.


что цель .align 8?

Выравнивание означает корректировку адреса, чтобы делиться с определенным количеством без остатка. В первом случае метка ele1 будет иметь адрес, делящийся на 8. Если предыдущий машинный код завершится на некотором неразделимом адресе, компилятор добавит несколько байтов (обычно nop-подобных инструкций), чтобы заполнить пробел, пока следующий возможный адрес не будет выполнен требования align.

Выравнивание важно для производительности контроллера памяти, так как они обычно работают с группой байтов внутри, например, имеют возможность извлекать четырехзначное число как 8 байтов только из 8-выровненного адреса. Если вы попросите его получить четырехзначное слово из не выровненного адреса, он выберет два 8-байтных набора из (address & -8) и ((address & -8)+8) и прочитает итоговый 8-байтовый результат из середины этих выбранных 16 байтов. (на x86 .. на других платформах неприглаженный доступ к памяти может быть даже недействительной, что приводит к тому, что ЦП получает сигнал ловушки, чтобы запустить обработчик аварий в этом случае).

(почему побитовое И с -8 делает адрес 8-выровнены? -8 = 0xF..F8 = 0b11 ... 11000 => последние 3 бита устанавливается в ноль => делится на 8 исполнено)