Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm для начинающих > Как вызвать процедуру по метке


Автор: Курсант 15.8.2017, 11:04
Всем привет! Решил освоить язык ассемблера... Пока есть небольшие проблемы с синтаксисом. Накорябал вот такой вот исходник:
Код

format PE GUI 4.0

entry Start

section '.text' code executable

Start:
  push 3
  push Bytes1
  push Bytes2
  push 0
  call [func_1]
  sub eax, 6
  jnz Start
  push 0
  call [func_2]
  jmp Start

section '.data' data readable

Bytes1:
db 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 0
Bytes2:
db 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 63, 0

section '.idata' data import readable

dd 0, 0, 0, RVA lib_name_1, RVA lib_table_1
dd 0, 0, 0, RVA lib_name_2, RVA lib_table_2
dd 0, 0, 0, 0

lib_table_1:
func_1 dd RVA pointer1
dd 0
lib_table_2:
func_2 dd RVA pointer2
dd 0

lib_name_1:
db 'user32.dll', 0
lib_name_2:
db 'kernel32.dll', 0

pointer1:
dw 0 
db 'MessageBoxA', 0
pointer2:
dw 0
db 'ExitProcess', 0


Всё работает. Теперь хочу попробовать вызвать функцию, но не с помощью макроса proc, а хардкорно, с помощью адреса. Т.е. пытаюсь изменить код следующим образом:
Код

format PE GUI 4.0

entry Start

section '.text' code executable

Start:
  push 3
  push Bytes1
  push Bytes2
  push 0
  call [routine]
  sub eax, 6
  jnz Start
  push 0
  call [func_2]
  jmp Start

routine:
  call [func_1]
  ret

section '.data' data readable

Bytes1:
db 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 0
Bytes2:
db 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 63, 0

section '.idata' data import readable

dd 0, 0, 0, RVA lib_name_1, RVA lib_table_1
dd 0, 0, 0, RVA lib_name_2, RVA lib_table_2
dd 0, 0, 0, 0

lib_table_1:
func_1 dd RVA pointer1
dd 0
lib_table_2:
func_2 dd RVA pointer2
dd 0

lib_name_1:
db 'user32.dll', 0
lib_name_2:
db 'kernel32.dll', 0

pointer1:
dw 0 
db 'MessageBoxA', 0
pointer2:
dw 0
db 'ExitProcess', 0


Но компилятор ругается на call [routine], мол, error: operand size not specified.
Вопрос: что я делаю не так.

Ну и вообще хотелось бы взять несколько уроков по ассемблеру у более опытных товарищей. С помощью TeamViewer. За вознаграждение smile

Автор: JAPH 23.8.2017, 20:42
Дело в том, что в fasm метка и обозначает адрес, поэтому, чтобы вызвать процедуру по метке, достаточно написать
Код

        call   routine

Тогда код скомпилируется. Но работать пока не будет, поскольку когда routine вызовет MessageBoxA, она некорректно передаст ей параметры, ведь на стеке окажется адрес возврата к команде, следующей за call routine. Поэтому нужно переписать эту процедуру, например, так:
Код

routine:
        jmp     [func_1]


О квадратных скобках в fasm можно думать как об операторе разыменования * в С. Если нужно получить значение по адресу a, пишут [a]. Если при этом размер этого значения не удается понять по контексту (по размеру второго операнда или по директиве, с которой была объявлена метка а), то его можно указать явно, например, dword [a].

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)