Nur ein kurzes Beispiel, wie MOVS
funktioniert (und andere aus der "String" -Befehlsfamilie sind ähnlich).
Zuerst brauchen Sie Speicherplatz im Speicher, in Ihrem Fall muss also filename
erweitert werden.
MAX_FILE_NAME_LENGTH EQU 128
filename db MAX_FILE_NAME_LENGTH dup (?) ; reserving enough space for "string"
img1 db 'img1.bmp',0
img1length equ $-img1
img2 db 'img2.bmp',0
img2length equ $-img2
Nun img2
"string" in filename
... img2
ist die Adresse in den Speicher, in dem die folgenden img2length
Bytes definiert werden durch die db
oben (einschließlich des Null-Separator) zu kopieren. Und Zieladresse ist das filename
Symbol. Die MOVS
kopiert Daten von ds:si
(si
als "Quelle") zu es:di
(di
als "Ziel").
...
; make sure the DS and ES are set up correctly, if you use data segment, then
; (this can be done just once, if you don't change ds/es in your code any more)
mov ax, @data
mov ds, ax
mov es, ax
cld ; DF=0, if you don't plan to use DF=1 elsewhere
; DF=0 means, that the "string" instructions increment SI/DI
; DF=1 would make them run backwards, decrementing addresses
; (that's handy when implementing "memmove" with overlapping areas)
...
...
; now prepare registers (except ds+es) for `rep movsb` variant
mov cx, img2length ; how many bytes to copy (numeric value)
lea si, [img2] ; offset img2 into SI
lea di, [filename] ; offset filename into DI
rep movsb ; copy "img2length" bytes from ds:si to es:di
; check memory in debugger, the reserved area at "filename" should
; now contain the copied string, including the zero terminator
; WARNING, if you forget about reserved space limitations, and define
; img2 string longer than MAX_FILE_NAME_LENGTH, the code above will
; merrily overwrite more memory than expected, destroying values in memory
; beyond the filename buffer
...
Eine weitere Variante mit Zeigern Beispiel:
Gängige Praxis ist Wert zu übergeben als Argument zu funktionieren, in diesem Fall, dass Sie den Anrufer fragen ds:dx
vor OpenFile
Aufruf voreinzustellen, dann weglassen Sie einfach den dx
Setup-Code in der Prozedur, und Sie sind fertig, Beispiel:
; arguments: ds:dx = pointer to ASCIIZ file name
; returns (and modifies): ax = file handle
; in case of file error "..." happens
proc OpenFile
mov ax, 3D00h ; ah = 3D "open file", al = 0 "read-only"
int 21h
jc openerror1
ret
openerror1:
... ; probably terminate app any way in case of error
dann vor jedem c alle richten Sie ds: dx, und nach dem Laden der Datei-Handle, wie Sie wollen:
img1 db 'img1.bmp',0
img1FileHandle dw 2 ; DW, because handle is 16 bit "wide" (AX = 16 bits)
; 2 == STDERR, until the code will run OpenFile and store real handle
Es ist auch möglich, diese Dinge in Globals in Erinnerung zu bringen:
...
; let's pretend the DS was already set before
mov dx, offset img1
call OpenFile
mov [img1FileHandle],ax
...
Daten wie diese aufgebaut wird , und dann lesen Sie sie aus dem Speicher innerhalb OpenFile
, aber wenn Sie versuchen, das zu schreiben, werden Sie sehen, es ist ziemlich umständlich, Argumente in Registern zu übergeben ist einfacher ... bis zu einem Punkt, bis Ihr Code komplex genug wird, um zu vergessen, welche Prozedur braucht was in welchem Register, und plötzlich wird es ein bisschen durcheinander.
Von dort ist es besser, einige offizielle Aufrufkonvention, wie Cdecl und ähnliche, aber die meisten der Aufrufkonventionen für 16b/32b-Modi verwendet Stapel für die Weitergabe von Argumenten, die wiederum ein bisschen mühsam ist, von Hand zu schreiben, und auch führt schlechter als Werte durch Register. Für kleine pure asm-Anwendungen können Sie die Argumente/Ergebnisse jeder Prozedur so optimieren, wie sie passen, und einfach jede Prozedur mit einer klaren Beschreibung der verwendeten Register kommentieren.
Sie können nur einen Zeiger darin speichern. Kennst du C? Du könntest es natürlich auch kopieren, aber dann brauchst du genug Platz (übrigens ist ein Zeiger auch mehr als ein Byte). – Jester
Sie können auch entscheiden, dass 'OpenFile' erfordert, dass der Aufrufer den' ds: dx' bereits so voreinstellt, dass er auf den Dateinamen zeigt, also wird es Prozedurargument sein. Dann können Sie tun 'mov dx, offset img1'' Aufruf OpenFile' .. und es ist auch üblich, Wert in 'ax' aus der Prozedur zurückgeben, so wieder der Aufrufer wird verantwortlich sein, den Griff irgendwo zu speichern. Auf diese Weise können Sie die 'OpenFile' für verschiedene Dateien gleichzeitig wiederverwenden. Vielleicht etwas über die Vorteile der funktionalen Programmierung lesen (nur nicht überanstrengt werden, manche Leute springen zu schnell auf diesen Weg, ohne zu verstehen, wie praktisch SW anti-Fn ist). – Ped7g