Почему мы не можем напрямую ссылаться на адрес памяти, используя регистр esp? - PullRequest
0 голосов
/ 05 апреля 2019

Ниже приведена программа сборки x86, предназначенная для сборки NASM под 64-битным CentOS через удаленный терминал, которая работает абсолютно нормально при использовании вместе с программой на Си.

section .data
section .text
        global  strlen

strlen:
        push    ebp
        mov     ebp, esp                ; obtain the address of the
        mov     eax, DWORD [ebp+8]      ; address of string to eax

        xor     ecx, ecx                ; initialize counter to zero

count_loop:
        mov     bl, [eax]               ; obtain the address of the 1st character
        cmp     bl, 0                   ; check the null value
        je      length_exit             ; exit if the null-character is reached
        inc     ecx                     ; increment counter
        inc     eax                     ; increment the address
        jmp     count_loop              ; start the loop again

length_exit:
        mov     eax, ecx                ; return ecx
        pop     ebp                     ;
        ret

Прежде всего, это 32-битная или 64-битная программа? Если это 32-битная программа, почему в названии функции нет символа подчеркивания (_)?

Я знаю, что следующий фрагмент кода создает кадр стека:

push    ebp
mov     ebp, esp                ; obtain the address of the
mov     eax, DWORD [ebp+8]      ; address of string to eax

но зачем нам сохранять ebp? Почему мы не можем просто написать следующее? :

 move eax, DWORD [esp+8]

И зачем нам здесь приведение типов?

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

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

Если это 32-битная программа, почему в названии функции нет символа подчеркивания (_)?

Потому что это не Windows.

Системы Linux / ELF не используют ведущий _ в любом режиме, независимо от архитектуры процессора.

Почему мы не можем просто написать следующее ?: move eax, DWORD [esp+8]

Можно. (Если вы правильно написали mov) . Фактически, компиляторы по умолчанию используют -fomit-frame-pointer, когда включена оптимизация, поэтому они используют только EBP в качестве указателя кадра в функциях с массивами C99 переменной длины или alloca.

32 и 64-битный режим позволяют ESP быть базовым адресом для режимов адресации, в отличие от 16-битного режима, где [sp+2] был не кодируемым.

Но помните, что если вы не нажали ebp, ESP по-прежнему указывает на обратный адрес, поэтому первый аргумент будет в [esp+4].

И зачем нам здесь приведение типов?

Вы нет. Операнд регистра подразумевает размер операнда.

(И это на самом деле не приведение типов, а просто спецификатор размера операнда. Он не будет выполнять преобразование с плавающей точкой в ​​int; вам придется использовать cvtss2si eax, [esp+4] для этого.)

Вам нужно только нужен спецификатор размера операнда для mem, немедленные инструкции, такие как cmp dword [esp+4], 0, которые будут неоднозначными между размером операнда байта / слова / слова. Или для инструкций типа movzx eax, byte [esp+4], где операнд регистра не не подразумевает размер для операнда памяти.

0 голосов
/ 05 апреля 2019

Причина кроется в схеме кодирования инструкций.
Таблица 2.2 из Раздел 2.1.5 Руководства Intel показывает возможные комбинации.

Это показывает, что (возможное) кодирование регистра ESP используется для указания того, что следует SIB байт (байт расширения инструкции):

Номенклатура [-] [-] означает, что SIB следует за байтом ModR / M.

Таким образом, кодировка для регистра ESP используется повторно для кодирования дополнительного байта инструкции, байта SIB.

В байте SIB кодировка команды для [ESP] также является исключением. Посмотрите на Таблица 2.3 .

...