Author Topic: changing data in function  (Read 3992 times)

ghjjkl

  • Member
  • **
  • Posts: 53
changing data in function
« on: June 20, 2014, 06:06:41 PM »
Hello again, i have some new novice's problem: how to pass address of some data to change it in function? I tried something like "invoke func,offset _address" and then, for example, in function: "mov ax, word ptr @data:[_address_which's_argument]", but it doesnt work, and ax contains yet another value i can't recognize   :(


nidud

  • Member
  • *****
  • Posts: 1370
    • https://github.com/nidud/asmc
Re: changing data in function
« Reply #1 on: June 20, 2014, 07:27:42 PM »
This was explained before in the samples we made  :P

The thing is, the address is segment:offset and your function only pass offset as an argument. To change data you need first to load the address into registers. Offset can be loaded into BX, DI, and SI. Segment can be loaded into DS and ES. To simplify this DS is usually set to @DATA in the beginning of the program. In that case you may do like this:
Code: [Select]
func proc string:word
mov bx,string ; load BX with offset of string
mov ax,ds:[bx]
DS is the default Data Segment, so this uses DS:
Code: [Select]
mov ax,[bx]
If the data you need to change is in another segment you need to pass this segment to the func:
Code: [Select]
func proc string:dword
les bx,string ; load ES:BX with address of string
mov ax,es:[bx]

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: changing data in function
« Reply #2 on: June 20, 2014, 07:34:59 PM »
i have to admit that i have never tried INVOKE in 16-bit code, but there's no reason it shouldn't work
that's because, in DOS days, i used MASM v 5.1 which did not support INVOKE

INVOKE'd functions require a PROTOtype, generally placed early in the file
(well - they require one if the INVOKE is to appear before the PROC)
the prototype tells the assembler how many arguments to expect, and their sizes
it may also tell the assembler which type of calling convention to use and the distance (NEAR or FAR)
for 32-bit programs, everything is NEAR, and the default is StdCall (defined in the .MODEL directive)
i am not sure how that works in 16-bit code
you'll have to consult the MASM manual for details

Code: [Select]
MyFunc  PROTO  <dist> <type> :WORD,:WORD,:WORD<dist> would be replaced with NEAR or FAR
<type> would be C, Pascal, Basic, StdCall, SysCall, etc
the default depends on the .MODEL and OPTION's (read the manual)
let's assume you use NEAR and StdCall.....

then, in the code section...
Code: [Select]
        .CODE

        INVOKE  MyFunc,arg1,arg2,arg3

and, the function

Code: [Select]
MyFunc PROC  NEAR StdCall _arg1:WORD,_arg2:WORD,_arg3:WORD

        mov     ax,_arg1
        mov     cx,_arg2
        mov     dx,_arg3
;
;
        ret

MyFunc ENDP

because you use NEAR and StdCall, the actual code generated might look like this
Code: [Select]
        push    arg3
        push    arg2
        push    arg1
        call    MyFunc

and....

Code: [Select]
MyFunc:
        push    bp
        mov     bp,sp

        mov     ax,[bp+4]
        mov     cx,[bp+6]
        mov     dx,[bp+8]
;
;
        leave
        ret     6

the LEAVE instruction is essentially the same as
Code: [Select]
        mov     sp,bp
        pop     bp

RET 6 returns and POP's 6 bytes off the stack (the passed arguments)

the behaviour is different for other <dist> and <type> parameters

ghjjkl

  • Member
  • **
  • Posts: 53
Re: changing data in function
« Reply #3 on: June 20, 2014, 07:40:21 PM »
um... i understand now, i didn't consider these problems to be the same... so sorry for this topic then and thanks for attention  :(

ghjjkl

  • Member
  • **
  • Posts: 53
Re: changing data in function
« Reply #4 on: June 20, 2014, 08:21:46 PM »
and what if i'll want to pass STRUC's address in function? Should i consider its members as [bx+number_of_bytes_before_some_member]?

nidud

  • Member
  • *****
  • Posts: 1370
    • https://github.com/nidud/asmc
Re: changing data in function
« Reply #5 on: June 20, 2014, 08:43:09 PM »
Yes.
or
Code: [Select]
.data
S1 STRUC
m1 db ?
m2 dw ?
S1 ENDS

S S1 <1,2>
.code
mov al,S.m1
mov ax,S.m2

lea bx,S
mov al,[bx].S1.m1
mov ax,[bx].S1.m2

assume  bx: ptr S1
mov al,[bx].m1
mov ax,[bx].m2

ghjjkl

  • Member
  • **
  • Posts: 53
Re: changing data in function
« Reply #6 on: June 20, 2014, 09:10:41 PM »
wow, that's cool  :t
what does "assume " mean with registers like bx? I used "assume" with registers like ds,cs,ss,es so far

nidud

  • Member
  • *****
  • Posts: 1370
    • https://github.com/nidud/asmc
Re: changing data in function
« Reply #7 on: June 20, 2014, 10:02:26 PM »
It means that BX point to a structure of type S1
Used mostly to reduce typing in MASM where members are private.
In TASM all members are public by default.
Code: [Select]
assume  bx: ptr S1 ; BX points to S1
mov al,[bx].m1
mov ax,[bx].m2
assume  bx:nothing ; BX back to normal

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: changing data in function
« Reply #8 on: June 20, 2014, 10:35:52 PM »
normally, we would pass the address of the entire structure
Code: [Select]
        INVOKE  MyFunc,offset S
then, in the routine, address the individual member(s)
you can use ASSUME, as nidud mentioned - but you don't have to
Code: [Select]
MyFunc PROC pStruct:WORD

        mov     bx,pStruct
        mov     al,[bx].S1.m1
        mov     cx,[bx].S1.m2

you could also pass the address of an individual member
Code: [Select]
        INVOKE  MyFunc,offset S.m2
« Last Edit: June 21, 2014, 12:01:41 AM by dedndave »

ghjjkl

  • Member
  • **
  • Posts: 53
Re: changing data in function
« Reply #9 on: June 22, 2014, 03:06:17 AM »
But what about arrays of STRUC's? If i want to change some members, using cycle,i could try:
Code: [Select]
some struc
a_ dw ?
b_ dw ?
some ends

.data

_some some 10 dup (<0,0>)

.code

mov ax,@data
mov ds,ax

xor bx,bx
.while bx<10
mov _some[bx].a_,5
inc bx
.endw
but it doesnt work.
Well, should i try this?
Code: [Select]
some struc
a_ dw ?
b_ dw ?
some ends

.data

_some some 10 dup (<0,0>)

.code

mov ax,@data
mov ds,ax

xor bx,bx
mov ax,10
cwd
mov dx,sizeof some
mul dx
.while bx<ax
mov _some[bx].a_,5
add bx,sizeof some
.endw

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: changing data in function
« Reply #10 on: June 22, 2014, 03:16:17 AM »
see if this works...

(see next post)

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: changing data in function
« Reply #11 on: June 22, 2014, 03:21:11 AM »
nix that one
try this

Code: [Select]
some struc
a_ dw ?
b_ dw ?
some ends

.data

_some some 10 dup (<0,0>)

.code

mov ax,@data
mov ds,ax

xor bx,bx
.while bx<(10*sizeof some)
mov [bx]._some.a_,5
add bx,sizeof some
.endw

ghjjkl

  • Member
  • **
  • Posts: 53
Re: changing data in function
« Reply #12 on: June 22, 2014, 04:12:28 AM »
no, sorry, it doesnt work.... should there be "mov [bx].some.a_,5" instead "mov [bx]._some.a_,5"?

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: changing data in function
« Reply #13 on: June 22, 2014, 05:42:04 AM »
maybe
Code: [Select]
    mov     _some[bx].some.a_,5
_some gets you the address
some gets you the structure offsets

ghjjkl

  • Member
  • **
  • Posts: 53
Re: changing data in function
« Reply #14 on: June 22, 2014, 04:23:31 PM »
wow, it works! Thanks, finally i got it     :biggrin: