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