LINUX.ORG.RU

Assembler. (eip). lea.

 


1

1

здрасьте, здрасьте люди добрые.

объясните синтаксис вот этого.


lea point(%rip), %rax
lea point, %rax

пожалуйста объясните в чем отличие между этими двумя инструкциями?

можно ли lea заменить mov?

lea это load effective address.

в одном случае берется смещение нечта размещенного в памяти, и названного point, смещение относительно - чего надо смотреть. в другом это смещение плюсуется к регистру команд. и кладется в rax.

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

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

Да

нет.
mov address, reg - это положить то, что находится по адресу address в регистр. а lea address, reg - это положить сам адрес в регистр

если компилять из си, то lea это «reg = &var»
а mov это «reg = var»

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

Ты путаешь мув и птр мув, из-за атт синтаксиса.

2ТС: lea это как мув, только умеет в адресную артфметику (база + смещение х множитель) в одной команде. В твоем случае разницы нет.

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

Ты путаешь мув и птр мув, из-за атт синтаксиса.

я ничего не путаю. читай описание команды lea.

для пробы можете отдизасемблить(должна быть команда lea c регистром bp/ebp/rbp)

void getadr(){
  int var;
  int *addr;
  addr = &var; 
}
alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

Ну я даже не знаю, что тут сказать

Starting program: /home/luke/lea/mov_val.exe 

Breakpoint 1, _start () at mov_val.s:7
7           movq    pointer, %rax
(gdb) info registers rax
rax            0x0                 0
(gdb) n
_exit () at mov_val.s:9
9           movq    $1, %rax
(gdb) info registers rax
rax            0x40                64
Starting program: /home/luke/lea/mov_pointer.exe 

Breakpoint 1, _start () at mov_pointer.s:7
7           movq    $pointer, %rax
(gdb) info registers rax
rax            0x0                 0
(gdb) n
_exit () at mov_pointer.s:9
9           movq    $1, %rax
(gdb) info registers rax
rax            0x402000            4202496
(gdb) 
luke ★★★★★
()
Ответ на: комментарий от luke

На ЛОРе не знают, чем отличается mov от lea. А еще говорят, что форумы не деградировали… как бы не так.

$ cat 1.c

struct xxx {
	int a;
	int b;
};

int * f1(struct xxx * x)
{
	return &x->b;
}

int f2(struct xxx * x)
{
	return x->b;
}

$ gcc -S -O2 1.c 
$ cat 1.s
	.file	"1.c"
	.text
	.p2align 4
	.globl	f1
	.type	f1, @function
f1:
.LFB0:
	.cfi_startproc
	leaq	4(%rdi), %rax
	ret
	.cfi_endproc
.LFE0:
	.size	f1, .-f1
	.p2align 4
	.globl	f2
	.type	f2, @function
f2:
.LFB1:
	.cfi_startproc
	movl	4(%rdi), %eax
	ret
	.cfi_endproc
.LFE1:
	.size	f2, .-f2
	.ident	"GCC: (Arch Linux 9.2.1+20200130-2) 9.2.1 20200130"
	.section	.note.GNU-stack,"",@progbits
Deleted
()
Ответ на: комментарий от alysnix

lea нужна для того, что бы загрузит в регист именно адрес, а не значение по нему. зачем надо?

  • например вызвается функция, которой нужен адрес переменной, а не ее значение - чтобы внутри функции что-то туда записать.

  • компилятор генерит код для вычисления длинного адресного выражения, которое не лезет в моду адресации процессора,например ptr[i]->field1[j]->field2->field… тогда пока адресация лезет в моду адресации, формируют ее, а как только она не лезет - грузят на регист вычиcленный адрес через lea, и опять копят моду адресации, опять вылезла - опять делают lea, и продолжают. так можно довольно компактно вычислить длинные адресные выражения. если б lea не было, вычислить такое было б можно, но очень длинно.

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

Так это же с регистром.

ну вот напиши на асме, как загрузить в регистр eax адрес локальной переменной х функции, если она стеке, без lea.

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

На ЛОРе не знают, чем отличается mov от lea.

ну я то знаю пока

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

Аааааа!!!! Дайте и я чего нибудь скажу.

Вобщем что понял я. mov может извлекать значения по адресу, который находится в операнде. Lea так не может. Lea не читает из памяти. Но вопрос как я понял в другом.

Чем отличается

lea p(%rip), eax
lea p, eax

Поправте пожалуйста, но кажется что ничем. Компилятор нижнюю версию преобразует до верхней версии сам. То есть он допишет %rip.

Вопрос что лежит в rip? И что значит lea p(%rip), eax? Вот о чем он спрашивает.

LGH
()
Ответ на: комментарий от Deleted

На ЛОРе не знают, чем отличается mov от lea

А ещё на ЛОРе не умеют читать. Вопрос был про «можно заменить», а не эквивалентность. В части случаев lea на mov заменяется в одну строчку.

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

А ещё на ЛОРе не умеют читать. Вопрос был про «можно заменить», а не эквивалентность. В части случаев lea на mov заменяется в одну строчку.

если адрес вычислим статически,тогда да. а если не вычислим статически - то только lea будет в одну строчку(если хватит моды адресации).

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

Без ануса не разберемся. Он шарит в ассемблер.

LGH
()

lea — операция арифметики, а не работы с памятью.

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

А не в одну строчку будет и с не статическим адресом.

В условии задачи про одну строчку не говорилось.

Конечно с lea жизнь проще.

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

Ну а что сейчас кроме flat модели-то есть?

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

Да ладно? А до этого случаем никакого mov bp, sp нет?

bp устанавливается до аллокирования локальных переменных. и он указывает на первую их них фактически.

а sp показывает на следующую свободную ячейку памяти, после локальных переменных, то есть - за последней локальной.

почувствуй разницу

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

bp зависит от конвенции (впрочем как и sp).

И ничего не мешает к sp добавить размер ячейки в дополнение к основному сдвигу.

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

bp

Ненужно.

$ cat 2.c
extern int h();

int f(int x)
{
	int a, b, c, d, e, f;
	return h(&x, &a, &b, &c, &d, &e, &f);
}
$ gcc -S -O2 2.c 
$ cat 2.s 
	.file	"2.c"
	.text
	.p2align 4
	.globl	f
	.type	f, @function
f:
.LFB0:
	.cfi_startproc
	subq	$56, %rsp
	.cfi_def_cfa_offset 64
	movl	%edi, 12(%rsp)
	leaq	24(%rsp), %rcx
	leaq	20(%rsp), %rdx
	leaq	16(%rsp), %rsi
	leaq	12(%rsp), %rdi
	subq	$8, %rsp
	.cfi_def_cfa_offset 72
	movq	%fs:40, %rax
	movq	%rax, 48(%rsp)
	xorl	%eax, %eax
	leaq	44(%rsp), %rax
	pushq	%rax
	.cfi_def_cfa_offset 80
	xorl	%eax, %eax
	leaq	48(%rsp), %r9
	leaq	44(%rsp), %r8
	call	h@PLT
	popq	%rdx
	.cfi_def_cfa_offset 72
	popq	%rcx
	.cfi_def_cfa_offset 64
	movq	40(%rsp), %rdx
	xorq	%fs:40, %rdx
	jne	.L5
	addq	$56, %rsp
	.cfi_remember_state
	.cfi_def_cfa_offset 8
	ret
.L5:
	.cfi_restore_state
	call	__stack_chk_fail@PLT
	.cfi_endproc
.LFE0:
	.size	f, .-f
	.ident	"GCC: (Arch Linux 9.2.1+20200130-2) 9.2.1 20200130"
	.section	.note.GNU-stack,"",@progbits

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

И ничего не мешает к sp добавить размер ячейки в дополнение к основному сдвигу.

Мешало, на 8086. Там вообще относительно sp ничего нельзя.

Так скомпилируется:

mov ax, [bp-1]
lea ax, [bp-1]

А так нет:

mov ax, [sp-1]
lea ax, [sp-1]

alysnix наверное просто не знает, почему так.

Deleted
()
Ответ на: комментарий от alysnix

надеюсь понятно зачем lea?

Вы мне это будете рассказывать?

Ну тогда встречный вопрос: надеюсь, понятно, почему bp на 8086 использовали?

Deleted
()
Ответ на: комментарий от Deleted

Ну во-первых не минус, а плюс, ибо стек растёт вниз.

Во-вторых мы говорили про адрес, там нужен mov и add.

luke ★★★★★
()

lea point(%rip), %rax ребята, что лежит в rip ? адрес следующей команды?

тогда что значит

point(%rip)?  как это читается ? адрес чего будет в  %rax? 
Assembler
() автор топика
Ответ на: комментарий от Assembler

lea point(%rip), %rax ребята, что лежит в rip ? адрес следующей команды?

смещение point+rip.

в доках по инструкциям интела и асму все есть.

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

Чуваки, вы зашли, чтобы сказать, что в доках по ассемблеру есть все?

Если не знаете, то что боитесь сказать об этои? Вот я туп, что скрывать это. Автор тоже умом не блещет. Поэтому он вас и просит помочь. Неужели сложно сказать что получится, если к rip прибавить смещение. Что за команда станет в результате? rip плюс смещение, что это?

LGH
()

@Assembler, попробуй-ка освоить отладчик gdb. Это просто:

# Сборка
as my_program.s -o my_program.o -g -ggdb
# Линковка
ld my_program.o -o my_program -g
# Запуск отладчика
gdb ./my_program

Дальше тебе надо будет установить точку останова на начало программы:

(gdb) break _start

Затем запустить программу:

(gdb) r

Теперь можешь посмотреть регистры в начале выполнения:

(gdb) info registers

если хочешь посмотреть только один регистр, например rax:

(gdb) info registers rax

Шаг к следующей инструкции:

(gdb) n

Так ты и ответишь на свои вопросы.

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

Чуваки, вы зашли, чтобы сказать, что в доках по ассемблеру есть все?

причем тут туп, не туп. ты не тупей прочих,…потому что знание ассемблера не признак ума, а скорее памяти и специфики работы.


lea — Load effective address

The lea instruction places the address specified by its first operand into the register specified by its second operand. Note, the contents of the memory location are not loaded, only the effective address is computed and placed into the register. This is useful for obtaining a pointer into a memory region or to perform simple arithmetic operations.

Syntax
lea <mem>, <reg32>

Examples
lea (%ebx,%esi,8), %edi — the quantity EBX+8*ESI is placed in EDI.
lea val(,1), %eax — the value val is placed in EAX. 
alysnix ★★★
()
Ответ на: комментарий от LGH

Неужели сложно сказать что получится, если к rip прибавить смещение. Что за команда станет в результате? rip плюс смещение, что это?

ip(instruction pointer) - это регистр меняемый процессором, показывающий на текущую исполняемую команду.

метка - это просто мнемоника адреса в памяти.

запись адреса (метка+ip) это к ip прибавляется этот адрес как число. чтобы понять зачем адресуют относительно ip надо вспомнить - «позиционно независимый код»:

Позиционно-независимый код - цитата с веба:

За всеми этими разговорами мы чуть было не забыли о третьем способе формирования адреса в программе. Это относительная адресация, когда адрес получается сложением адресного поля команды и адреса самой этой команды – значения счетчика команд. Код, в котором используется только такая адресация, можно загружать с любого адреса без всякой перенастройки. Такой код называется позиционно-независимым (position-independent).

вот в данном случае команда написана в стиле позиц.независимого кода.

у gcc есть опция -fPIC , что генерит Position Independent Code, если оно вам так приспичило.

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

Ну во-первых не минус, а плюс, ибо стек растёт вниз. Во-вторых мы говорили про адрес, там нужен mov и add.

Вашу мать, парни! Во-первых, что минус, что плюс, машине фиолетово. В машкоде для адресации со смещением записана константа со знаком, а процессор с ней всегда выполняет одно и то же действие: сначала расширение со знаком до разрядной сетки, а потом беззнаковое сложение.

Во-вторых,

mov rax, [variable]
lea rax, [rsp+rax+16]

Нет, тебе не нужен add для таких простых случаев.

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

Вы ассемблер на картинках только видели? Харе тупить!

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от alysnix

а мне это неинтересно

Если тебе это не интересно, зачем ты тут рассказываешь, про rbp, который для адресации стека на современном железе тупо не нужен?

Офигеть уровень: приходить учить других — это интересно, а самому открыть доки и понять, что говоришь ерунду — не интересно.

Deleted
()
Ответ на: комментарий от LGH

Если не знаете, то что боитесь сказать об этои? Вот я туп, что скрывать это. Автор тоже умом не блещет. Поэтому он вас и просит помочь. Неужели сложно сказать что получится, если к rip прибавить смещение. Что за команда станет в результате? rip плюс смещение, что это?

На IA-32 вы не могли использовать eip как операнд для АЛУ. Физически не было предусмотрено таких команд:

mov eax, eip    ; => ошибка компиляции
lea eax, [eip]  ; => ошибка компиляции
push eip        ; => ошибка компиляции

Адресация вида eip + смещение использовалась только для вызовов процедур и ветвлений.

Поэтому был такой костыль, чтобы добыть значение eip в регистр общего назначения:

	call .tmp
.tmp:
	pop eax

Поэтому невозможно было легко и просто без костылей написать кусок кода, который работает при загрузке по любому адресу памяти.

На amd64 соответствующие команды появились. Теперь можно адресовать переменные через rip + смещение.

Deleted
()
Ответ на: комментарий от Deleted

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

Это ты говорил не мне.

Всё что я хотел сказать, это

mov    ax, pointer
lea    ax, [pointer]

дают один и тот же результат

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

Слушай я хоть щас и пьяный, но я точно помню, кому что писал. А писал я про ваш спор с alysnix насчёт bp. Ты же мне начал втирать насчёт того что у меня там минусы вместо плюсов и т.п…. хз вообще, зачем. Хоть минусы, хоть плюсы, машине пофиг.

Deleted
()
Ответ на: комментарий от Deleted

Слушай я хоть щас и пьяный,

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

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

У тебя там вообще -1, что есть бред для стека. Хотя бы -2 написал. Машине-то пофиг, но конвенция есть конвенция. И про bp бреда я не писал (опять же конвенция).

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

потому что на лоре сидят мамкины борщевики

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