assembly x86 - how to move strings between variables -
(running assembly x86 through dosbox)
i'm using procedures load image (bmp file) , first 1 load file (open it):
proc openfile mov ah, 3dh xor al, al mov dx, offset filename int 21h jc openerror1 mov [filehandle], ax ret openerror1: mov dx, offset errormsg mov ah, 9h int 21h ret endp i want filename used global variable name of file - string of path thing have before running procs move right path filename variable.
filename db ? img1 db 'img1.bmp',0 img2 db 'img2.bmp',0 i thought it's kind of string transferring , found out movs command might helpful didn't manage understand way works.
just short example how movs works (and others "string" instruction family similar).
first need space in memory, in case filename has extended.
max_file_name_length equ 128 filename db max_file_name_length dup (?) ; reserving enough space "string" img1 db 'img1.bmp',0 img1length equ $-img1 img2 db 'img2.bmp',0 img2length equ $-img2 now copy img2 "string" filename... img2 address memory, following img2length bytes defined db above (including 0 separator). , target address filename symbol. movs copies data ds:si (si "source") es:di (di "destination").
... ; make sure ds , es set correctly, if use data segment, ; (this can done once, if don't change ds/es in code more) mov ax, @data mov ds, ax mov es, ax cld ; df=0, if don't plan use df=1 elsewhere ; df=0 means, "string" instructions increment si/di ; df=1 make them run backwards, decrementing addresses ; (that's handy when implementing "memmove" overlapping areas) ... ... ; prepare registers (except ds+es) `rep movsb` variant mov cx, img2length ; how many bytes copy (numeric value) lea si, [img2] ; offset img2 si lea di, [filename] ; offset filename di rep movsb ; copy "img2length" bytes ds:si es:di ; check memory in debugger, reserved area @ "filename" should ; contain copied string, including 0 terminator ; warning, if forget reserved space limitations, , define ; img2 string longer max_file_name_length, code above ; merrily overwrite more memory expected, destroying values in memory ; beyond filename buffer ... another variant pointers example:
common practice pass value function argument, in case may ask caller pre-set ds:dx ahead of openfile call, omit dx setup code in procedure, , done, example:
; arguments: ds:dx = pointer 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: ... ; terminate app way in case of error then ahead of each call set ds:dx, , after store file handle wish:
... ; let's pretend ds set before mov dx, offset img1 call openfile mov [img1filehandle],ax ... data being set this:
img1 db 'img1.bmp',0 img1filehandle dw 2 ; dw, because handle 16 bit "wide" (ax = 16 bits) ; 2 == stderr, until code run openfile , store real handle it's possible put things globals in memory, , read them memory inside openfile, if try write that, see it's quite cumbersome, passing arguments in registers simpler... point, until code gets complex enough forget procedure needs in register, , becomes bit of mess.
from there it's better follow official calling convention, cdecl , similar, of calling conventions 16b/32b modes did use stack passing arguments, again bit tedious write hand, , performs worse passing values registers. small pure asm applications feel free optimize each procedure arguments/results fit, , comment each procedure clear description registers used.
Comments
Post a Comment