Includelib kernel32.Lib
ExitProcess proto stdcall :dword
AddDig proto stdcall :dword, :dword
.code
main proc
invoke AddDig,5,3
Invoke ExitProcess,0
main endp
AddDig proc a1:dword, a2:dword
mov eax,dword ptr ss:[esp+08h]
mov ecx,dword ptr ss:[esp+0Ch]
add eax,ecx
ret 8
AddDig endp
End main
leave ~ mov esp,ebp
pop ebp
push ebp
mov ebp,esp
…
mov esp,ebp
pop ebp
Когда вызывается процедура с переменным числом параметров, необходимо программе-ассемблеру самой восстанавливать стек (смотрит сколько было загружено в стек)
Если ebp не меняется внутри процедуры, то esp можно просто восстановить перед выходом из процедуры (удаляя тем самым место, выделенное для локальных переменных), при этом сохраняя ebp для внешних процедур в стеке.
А то, что Ассемблер сохраняет значение esp, то это для случая если в стек заталкиваются параметры следующей процедуры и локальные переменные).
Уменьшать указатель стека на суммарный размер локальных переменных нужно для сохранения сами локальных переменных иначе они могут быть уничтожены вызовом процедур из текущей процедуры.
edx |
uses edx |
Local4 |
<-esp |
Local3 |
ebp-0Ch |
Local2 |
ebp-08h |
Local1 |
ebp-04h |
push ebp |
<-ebp |
ret addr |
ebp+04h |
3-й параметр - при call (1-й параметр – при invoke) |
ebp+08h |
2-й параметр - при call (2-й параметр – при invoke) |
ebp+0Ch |
1-й параметр - при call (3-й параметр – при invoke) |
ebp+10h |
Includelib kernel32.Lib
include kernel32.inc
include windows.inc
AddG proto stdcall :dword, :dword
.data
StrI byte "HELL!",0Dh,0Ah
.code
main proc
invoke AddG,addr StrI, sizeof StrI
Invoke ExitProcess,0
main endp
AddG proc a1:dword, a2:dword
sub esp,8
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov dword ptr ss:[ebp-04h],eax
invoke WriteConsoleA,dword ptr ss:[ebp-4],dword ptr ss:[ebp+08h],dword ptr ss:[ebp+0Ch],addr dword ptr ss:[ebp-08h],NULL
ret
;8888
AddG endp
End main
Если заголовок пуст, то пролог и эпилог ассемблер не ставит НАЛИЧИЕ ПРОЛОГА ИЛИ ЭПИЛОГА ЗАВИСИТ ОТ НАЛИЧИЯ ЗАГОЛОВКА ПРОЦЕДУРЫ.!!.
WrTeMess proc ArGG:Dword, AR2:DWORD
LOCAL FERT:DWORD, HND:DWORD
StrDisp proc uses eax, Arg_1_addrStrg:DWORD, Arg_2_sizeofStrg:DWORD
local HndlOutput:DWORD, WrittenChr:DWORD
00401013 /$ 55 push ebp ; wq.00401013(guessed Arg1,Arg2)
00401014 |. 8BEC mov ebp, esp
push eax
00401016 |. 83C4 F8 add esp, -8
00401019 |. 50
…..
pop eax
leave
Если вызов процедуры через call без описания аргументов в заголовке функции, то корректировка параметров с учетом только одного адреса возврата по ret, если invoke, то учесть еще push ebp.
add esp, -8
sub esp,8 - локальные (восстанавливает mov esp, ebp) сохраняют эти выделенные переменные от вызова подфункций и передачи для них параметров.
push ebp
mov ebp, esp гарантирует сохранность для внешней процедуры по условиям.
Можно
.code
start:
end start
-----------------------------------
main PROC
main ENDP
END main
----------------------------------
start:
main PROC
main ENDP
FName PROC
FName ENDP
end start
INCLUDE директива с помощью, которой можно включить информацию о глобальных переменных и начальные установки программы
Компоновщик определяет есть ли в программе внешние ссылки (вызовы процедур, находящихся в одной из библиотек объектных модулей link library). Компоновщик находит эти ссылки в объектном файле программы, копирует необходимые процедуры из библиотек, объединяет их вместе с объектным файлом (разрешение внешних ссылок) и создает исполняемый файл. Может создать файл перекрестных ссылок (map file), содержащий план полученного исполняемого файла.
Если используем описание переменны в заголовке, но не хотим, что бы ассемблер создавал заголовок необходимо воспользоваться директивами:
Option prologue:none
Option epilogue:none
Резюме:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ПРОЦЕДУРЫ
k/j != 0, тогда k – простое число, где
j – (2…k-1)
k – (3…N)
Псевдо код.
M ass[200] i=0;
for (k=3; k++; N)
for (j=2; j++; k-1)
if (k/j = 0) then BREAK
otherwise k - простое число
Mass[i]=k;
Начальные значения устанавливаются перед входом в цикл, а инкрементирование и проверка на выход в конце, тогда код короче.
include kernel32.inc
include windows.inc
include user32.inc
includelib kernel32.lib ; _ExitProcess@4
includelib user32.lib
BUFSIZE equ 20000
.data?
Massive dword BUFSIZE dup (?)
.data
Nmax dword 2000000
FrmStr byte "%d",0h ;@
Hnd dword ? ;@
WrittenCh dword ? ;@
.code
main proc
mov esi,0 ; esi=index 'Massive'
mov ecx,3 ;ecx = k
For1:
mov ebx,2 ; j=2
For2:
xor edx,edx
mov eax,ecx
div ebx
cmp edx,0
je Break
inc ebx
cmp ecx,ebx
jne For2
mov Massive[esi*4],ecx
;--------------------
pusha
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov Hnd,eax
invoke wsprintf,addr Massive[esi*4],addr FrmStr,ecx
invoke WriteConsoleA,Hnd,addr Massive[esi*4],4,addr WrittenCh,NULL
popa
;--------------------
inc esi
Break:
inc ecx ; ecx=k => ++
cmp ecx,dword ptr Nmax
jne For1
