GerdtR, при компиляции команды типа mov eax,[var] fasm генерирует код команды и запоминает, что на таком-то месте был адрес var. В двоичном формате это знание успешно игнорируется, но в более сложных форматах в той или иной форме есть список
перемещаемых элементов aka relocations, в котором записано, что там-то и там-то находятся адреса. Загрузчик библиотеки уже знает, где именно в памяти размещена библиотека, и проходит по списку перемещаемых элементов, корректируя адреса. В результате после загрузки mov eax,[var] читает откуда надо.
IgorA, неверно. Нет никакой локальной копии всей библиотеки для конкретного приложения.
GerdtR, глобальных
переменных действительно лучше избегать, но по причинам, не связанным с библиотеками: глобальные переменные, к которым много обращений, могут существенно усложнить выяснение "какая собака здесь порылась, что теперь у переменных какие-то странные значения"; с глобальными переменными обязательно будут проблемы, если к ним есть обращение из двух потоков параллельно. Глобальные
константы - возможно, вычисляемые и записываемые один раз при инициализации, но не при работе - пожалуйста. И, между прочим, каждый адрес глобальной переменной - 4 байта в коде и лишняя запись в таблице перемещаемых элементов. Лучше использовать локальные переменные:
Code: Select all
include 'proc32.inc'
proc MyAwesomeProc
locals
var1 dd ?
var2 dd ?
endl
mov [var1],eax
ret
endp
Для справки: это транслируется примерно в
Code: Select all
if used MyAwesomeProc
MyAwesomeProc:
push ebp
mov ebp, esp
sub esp, 8 ; allocate space for two dword variables
mov [ebp-4], eax
leave
ret
end if
Локальные переменные создаются на стеке, для их адресации используется регистр ebp. Если регистров не хватает и очень хочется задействовать ebp для вычислений, то можно адресовать и напрямую через esp:
Code: Select all
proc MyAwesomeProc
sub esp, 8 ; allocate space for two dwords
virtual at esp
.var1 dd ?
.var2 dd ?
end virtual
mov [.var1], eax
add esp, 8 ; restore the stack
ret
endp
но тогда придётся очень внимательно следить за всеми операциями со стеком, которые сбивают esp; кроме того, адресация через esp экономит на прологе push ebp/mov ebp,esp, но теряет по байту на каждом обращении к переменным.