Ответ 1
На самом деле это вычисленная таблица jmp, где 0x402680 является адресом tabele, а rax - индексом 8-байтового (qword) указателя.
Что означает следующая строка:
...
401147: ff 24 c5 80 26 40 00 jmpq *0x402680(,%rax,8)
...
Что означает звездочка перед адресом памяти? Кроме того, что это значит, когда отсутствует способ доступа к памяти, это первое значение регистра?
Обычно это что-то вроде ( "% register",% rax, 8), но в этом случае у него нет первого регистра.
Любые советы?
На самом деле это вычисленная таблица jmp, где 0x402680 является адресом tabele, а rax - индексом 8-байтового (qword) указателя.
Синтаксис сборки AT & T:
q
для quad и т.д.)
Регистры %
и немедленные значения с помощью $
DISP(BASE, INDEX, SCALE)
(DISP + BASE + INDEX * SCALE)*
(в отличие от относительного IP)Итак, у вас есть jmpq
для перехода к абсолютному адресу, который хранится в %rax * 8 + 0x402680
, и длится четыре слова.
Получение элементов в синтаксисе Intel всегда делает вещи более ясными:
FF24C5 80264000 JMP QWORD PTR [RAX*8+402680]
Это переход к адресу, содержащемуся в памяти. Адрес хранится в памяти по адресу rax*8+0x402680
, где rax
- текущее значение rax
(при выполнении этой команды).
jmpq
- это просто не условный переход к данному адресу. "Q" означает, что мы имеем дело с четырьмя словами (длиной 64 бит).
*0x402680(,%rax,8)
: Это способ записи адреса в сборке x-86. Вы правильно говорите, что обычно есть регистр перед первой запятой, но вы по-прежнему придерживаетесь тех же правил, если не указан регистр.
Формат работает следующим образом:
D(reg1, reg2, scalingFactor)
где D обозначает смещение. Смещение в основном просто целое. reg1
- это первый или базовый регистр. reg2
- второй регистр, а scalingFactor
- один из 2, 4, 8 (может быть, даже 1, но я не уверен в этом). Теперь вы можете получить свой адрес, просто добавив значения таким образом: Смещение + (значение в reg1
) + scalingFactor
* (значение в reg2
).
Я не совсем уверен, что такое звездочка перед адресом, но я предполагаю, что это означает, что значение смещения сохраняется на этом адресе.
Надеюсь, что это поможет.
Как писал Некролис, синтаксис Intel делает его более очевидным, но RTN действительно яснее. Строка
jmpq *0x402680(,%rax,8)
будет описываться в RTN с помощью:
RIP <- M[0x402680 + (8 * RAX)]
где M
- системная память.
Таким образом, мы можем написать общий вид jmpq *c(r1, r2, k)
, где c
- непосредственная константа, r1
и r2
- регистры общего назначения, а k
- либо 1 (по умолчанию), 2, 4 или 8:
RIP <- M[c + r1 + (k * r2)]
Минимальный пример
Чтобы прояснить ситуацию:
.data
# Store he address of the label in the data section.
symbol: .int label
.text
# Jumps to label.
jmp *symbol
label:
Без *
он будет переходить к адресу symbol
в разделе .data
и к segfault.
Я чувствую, что этот синтаксис немного противоречив, потому что для большинства инструкций:
mov symbol, %eax
mov label, %eax
уже перемещает данные на symbol
адреса, а $symbol
используется для адреса. Синтаксис Intel более последовательный в этом вопросе, поскольку он всегда использует []
для разыменования.
*
Это, конечно, мнемоника для оператора разыменования C *ptr
.