News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

16-bit MASM blues...

Started by turboscrew, December 13, 2013, 04:37:37 PM

Previous topic - Next topic

Gunther

Jochen,

Quote from: jj2007 on December 28, 2013, 06:13:56 AM
My point was that the endp delimits the scope of a procedure, and that ret has a different meaning above and below the endp.

that's clear and it has to do with MASM/JWASM gadgets. But turboscrew has some difficulties with that stuff. That was my point.

Gunther
You have to know the facts before you can distort them.

turboscrew

No Linux here, since this "department" is about 16-bit assembly - architecture that Linux won't run on.

Also, I can use, say, AT&T, but that doesn't help understanding the "meaning" of PROC (and 16-bit Intel assembly).

Anyway, since RET has different meaning inside and outside of procedure block tells me that procedure block has some (essential) role in 16-bit x86 assembly, but what?


FORTRANS

Hi,

   As has been mentioned, PROC and ENDP can cause some actions
to occur.  However at its most simple usage, it has little effect.  See
the code generated for the following two routines.


      13 0000  50 CRLF:   PUSH    AX      ; Save affected registers
      14 0001  52         PUSH    DX
      15
      16 0002  B2 0D         MOV     DL,13   ; CR
      17         SCALL CONOUT
      18 0004  B4 02                 1 MOV AH,DOSF_CONOUT
      19 0006  CD 21                 1 INT 21H
      20 0008  B2 0A         MOV     DL,10   ; LF
      21         SCALL CONOUT
      22 000A  B4 02                 1 MOV AH,DOSF_CONOUT
      23 000C  CD 21                 1 INT 21H
      24
      25 000E  5A         POP     DX      ; Restore registers
      26 000F  58         POP     AX
      27
      28 0010  C3         RET
      29
      30 ; - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -
      31 0011 NewLine PROC
      32
      33 0011  50         PUSH    AX      ; Save affected registers
      34 0012  52         PUSH    DX
      35
      36 0013  B2 0D         MOV     DL,13   ; CR
      37         SCALL CONOUT
      38 0015  B4 02                 1 MOV AH,DOSF_CONOUT
      39 0017  CD 21                 1 INT 21H
      40 0019  B2 0A         MOV     DL,10   ; LF
      41         SCALL CONOUT
      42 001B  B4 02                 1 MOV AH,DOSF_CONOUT
      43 001D  CD 21                 1 INT 21H
      44
      45 001F  5A         POP     DX      ; Restore registers
      46 0020  58         POP     AX
      47
      48 0021  C3         RET
      49
      50 0022 NewLine ENDP
      51 ; - - - - - - - - - - - - - - - - - - -


   Here there is no difference in the code generated when using
PROC/ENDP or a simple label.  So if you do not apply options,
and use it correctly, PROC/ENDP acts as a visual delimiter for
your routine.

Regards,

Steve N.

Gunther

Hi  turboscrew,

Quote from: turboscrew on December 28, 2013, 07:24:11 AM
No Linux here, since this "department" is about 16-bit assembly - architecture that Linux won't run on.

take care, Linux can run on 16 bit machines. I've done that a few years ago on an embedded system.

But that's not my point. I've attached the archive hello.zip. It contains 4 files. HELLOM.ASM is the MASM/JWASM/TASM source for a simple hello world COM program. HELLON.ASM is the YASM/NASM equivalent. The functionality is the same and the differences are not so hard. The code should be self explanatory and is good commented. I hope that helps.

Gunther
You have to know the facts before you can distort them.

turboscrew

(ELKS is a subset, not full Linux. There is also uClinux, but it's not considered full linux either.)

Well, it still hasn't sunk into my hard head what PROC really is (or procedure block).
The only "stand up" effect I have found out this far is that the assembler takes the labels
within a procedure block as locals.


dedndave

a PROC is typically a subroutine - it's that simple
whenever you think of CALL, think PROC   :P

if you come from C world
PROC = {
ENDP = }

FORTRANS

Hi,

   As Dave says, PROC and ENDP (help to) define a subroutine
or procedure.  In my earlier example, it did not do anything
except provide "labels" for the start and end of the routine.
In this example the PROC statement will have an option applied
to it, and that will affect how the assembler treats the code
within that PROCedure.


      13 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      14 0000 CRLF    PROC    FAR
      15 0000  50         PUSH    AX      ; Save affected registers
      16 0001  52         PUSH    DX
      17
      18 0002  B2 0D         MOV     DL,13   ; CR
      19         SCALL CONOUT
      20 0004  B4 02                 1 MOV AH,DOSF_CONOUT
      21 0006  CD 21                 1 INT 21H
      22 0008  B2 0A         MOV     DL,10   ; LF
      23         SCALL CONOUT
      24 000A  B4 02                 1 MOV AH,DOSF_CONOUT
      25 000C  CD 21                 1 INT 21H
      26
      27 000E  5A         POP     DX      ; Restore registers
      28 000F  58         POP     AX
      29
      30 0010  CB         RET
      31
      32 0011 CRLF    ENDP
      33 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      34 0011 NewLine PROC    NEAR
      35
      36 0011  50         PUSH    AX      ; Save affected registers
      37 0012  52         PUSH    DX
      38
      39 0013  B2 0D         MOV     DL,13   ; CR
      40         SCALL CONOUT
      41 0015  B4 02                 1 MOV AH,DOSF_CONOUT
      42 0017  CD 21                 1 INT 21H
      43 0019  B2 0A         MOV     DL,10   ; LF
      44         SCALL CONOUT
      45 001B  B4 02                 1 MOV AH,DOSF_CONOUT
      46 001D  CD 21                 1 INT 21H
      47
      48 001F  5A         POP     DX      ; Restore registers
      49 0020  58         POP     AX
      50
      51 0021  C3         RET
      52
      53 0022 NewLine ENDP
      54 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


   The assembler now knows that the RETurn instructions are of
different types.  And makes the appropriate change to a near or
far return.

   So the PROC/ENDP tells the MASM assembler what characteristics
should be applied to a block of code.  See the listing of the variables
to see if anything happened.


                N a m e          Type Value Attr

CRLF . . . . . . . . . . . . . .  F PROC 0000 CODE Length = 0011

NEWLINE  . . . . . . . . . . . .  N PROC 0011 CODE Length = 0011


   You can apply an option to the PROC directive and make a
listing to see what changes.  In my earlier example, I showed
that you can avoid using the PROC and ENDP directives if you
want.

Regards,

Steve N.

turboscrew

So, did I understand it right:

PROC - ENDP as such do nothing (except with options, like NEAR or FAR), but really define a scope where other
(more or less procedure-oriented) options, directives and the like apply?

And it looks like ASSUME DS:segment really tells the assembler what kind of code to emit for data accesses: like far + segment or near.

dedndave

there are a few other qualifiers that may be added to the PROC line, as well

for example, USES preserves and restores registers for you
MyFunc PROC USES BX SI DI arg1:WORD

    ret

MyFunc ENDP


also, PROC labels are PUBLIC, by nature, but can be made PRIVATE
and - the calling convention that you specify at the beginning of the program may be overridden
refer to the Masm Programmers Guide - available in PDF, let me know if you need a link

turboscrew

I saw a link to the 2004-2012 archive site, but I haven't yet registered there.

But roughly, the PROC - ENDP defines a scope?

dedndave

sure - that refers to the scope of (local) variables on the stack for the instance of the call
when the function returns, the variables are lost - thus, they have limited scope

Gunther

turboscrew,

Quote from: turboscrew on December 29, 2013, 09:18:47 AM
But roughly, the PROC - ENDP defines a scope?

Yes. These are special directives (sometimes called pseudo operations, pseudo directives and the like). You should have a look into that source, especially chapter 8.

Gunther
You have to know the facts before you can distort them.

MichaelW

An arbitrarily complex procedure and invoke, done in 32-bit code for convenience.

;========================================================================================
include \masm32\include\masm32rt.inc
.686
;========================================================================================
.data
    dd1   dd    12345678h
    r8    REAL8 1234.56789
    dq1   dq    1234567812345678h
    rect  RECT  <1,2,3,4>
.code
;========================================================================================
proc1 proc uses gs ebx edi esi param1:DWORD, param2:REAL8, param3:QWORD, param4:RECT
    LOCAL local1:DWORD
    LOCAL local2:REAL8
    LOCAL local3:QWORD
    LOCAL local4:RECT
    LOCAL local5[4]:DWORD
    push  param1
    pop   local1
    fld   param2
    fstp  local2
    fild  param3
    fistp local3
    push param4.left
    pop  local4.left
    push param4.top
    pop  local4.top
    push param4.right
    pop  local4.right
    push param4.bottom
    pop  local4.bottom
    nop
    printf("%Xh\n",local1)
    printf("%f\n",local2)
    printf("%I64Xh\n",local3)
    printf("%d\t%d\t%d\t%d\n\n",local4.left,local4.top,local4.right,local4.bottom)
    nop
    mov eax, param1
    mov local5, eax
    mov local5[4], eax
    mov local5[8], eax
    mov local5[12], eax
    xor eax, eax
    add eax, local5
    add eax, local5[4]
    add eax, local5[8]
    add eax, local5[12]
    ret
proc1 endp
;========================================================================================
start:
;========================================================================================
    mov eax, DWORD PTR dq1
    mov edx, DWORD PTR dq1+4
    invoke proc1, dd1, r8, edx::eax, rect
    mov ecx, 4
    cdq
    div ecx
    printf("%Xh\n\n",eax)
    inkey
    exit
;========================================================================================
end start


12345678h
1234.567890
1234567812345678h
1       2       3       4

12345678h


00401000   $ 55             PUSH EBP
00401001   . 8BEC           MOV EBP,ESP
00401003   . 83C4 CC        ADD ESP,-34
00401006   . 0FA8           PUSH GS
00401008   . 53             PUSH EBX
00401009   . 57             PUSH EDI
0040100A   . 56             PUSH ESI
0040100B   . FF75 08        PUSH DWORD PTR SS:[EBP+8]
0040100E   . 8F45 FC        POP DWORD PTR SS:[EBP-4]
00401011   . DD45 0C        FLD QWORD PTR SS:[EBP+C]
00401014   . DD5D F4        FSTP QWORD PTR SS:[EBP-C]
00401017   . DF6D 14        FILD QWORD PTR SS:[EBP+14]
0040101A   . DF7D EC        FISTP QWORD PTR SS:[EBP-14]
0040101D   . FF75 1C        PUSH DWORD PTR SS:[EBP+1C]
00401020   . 8F45 DC        POP DWORD PTR SS:[EBP-24]
00401023   . FF75 20        PUSH DWORD PTR SS:[EBP+20]
00401026   . 8F45 E0        POP DWORD PTR SS:[EBP-20]
00401029   . FF75 24        PUSH DWORD PTR SS:[EBP+24]
0040102C   . 8F45 E4        POP DWORD PTR SS:[EBP-1C]
0040102F   . FF75 28        PUSH DWORD PTR SS:[EBP+28]
00401032   . 8F45 E8        POP DWORD PTR SS:[EBP-18]
00401035   . 90             NOP
00401036   . FF75 FC        PUSH DWORD PTR SS:[EBP-4]                ; /<%X>
00401039   . 68 24304000    PUSH test.00403024                       ; |format = "%Xh
"
0040103E   . FF15 20204000  CALL DWORD PTR DS:[<&msvcrt.printf>]     ; \printf
00401044   . 83C4 08        ADD ESP,8
00401047   . FF75 F8        PUSH DWORD PTR SS:[EBP-8]
0040104A   . FF75 F4        PUSH DWORD PTR SS:[EBP-C]                ; /<%f>
0040104D   . 68 2C304000    PUSH test.0040302C                       ; |format = "%f
"
00401052   . FF15 20204000  CALL DWORD PTR DS:[<&msvcrt.printf>]     ; \printf
00401058   . 83C4 0C        ADD ESP,0C
0040105B   . FF75 F0        PUSH DWORD PTR SS:[EBP-10]
0040105E   . FF75 EC        PUSH DWORD PTR SS:[EBP-14]               ; |
00401061   . 68 34304000    PUSH test.00403034                       ; |format = "%I64Xh
"
00401066   . FF15 20204000  CALL DWORD PTR DS:[<&msvcrt.printf>]     ; \printf
0040106C   . 83C4 0C        ADD ESP,0C
0040106F   . FF75 E8        PUSH DWORD PTR SS:[EBP-18]               ; /<%d>
00401072   . FF75 E4        PUSH DWORD PTR SS:[EBP-1C]               ; |<%d>
00401075   . FF75 E0        PUSH DWORD PTR SS:[EBP-20]               ; |<%d>
00401078   . FF75 DC        PUSH DWORD PTR SS:[EBP-24]               ; |<%d>
0040107B   . 68 40304000    PUSH test.00403040                       ; |format = "%d %d %d %d

"
00401080   . FF15 20204000  CALL DWORD PTR DS:[<&msvcrt.printf>]     ; \printf
00401086   . 83C4 14        ADD ESP,14
00401089   . 90             NOP
0040108A   . 8B45 08        MOV EAX,DWORD PTR SS:[EBP+8]
0040108D   . 8945 CC        MOV DWORD PTR SS:[EBP-34],EAX
00401090   . 8945 D0        MOV DWORD PTR SS:[EBP-30],EAX
00401093   . 8945 D4        MOV DWORD PTR SS:[EBP-2C],EAX
00401096   . 8945 D8        MOV DWORD PTR SS:[EBP-28],EAX
00401099   . 33C0           XOR EAX,EAX
0040109B   . 0345 CC        ADD EAX,DWORD PTR SS:[EBP-34]
0040109E   . 0345 D0        ADD EAX,DWORD PTR SS:[EBP-30]
004010A1   . 0345 D4        ADD EAX,DWORD PTR SS:[EBP-2C]
004010A4   . 0345 D8        ADD EAX,DWORD PTR SS:[EBP-28]
004010A7   . 5E             POP ESI
004010A8   . 5F             POP EDI
004010A9   . 5B             POP EBX
004010AA   . 0FA9           POP GS                                   ;  Modification of segment register
004010AC   . C9             LEAVE
004010AD   . C2 2400        RETN 24
004010B0 >/$ A1 0C304000    MOV EAX,DWORD PTR DS:[40300C]
004010B5  |. 8B15 10304000  MOV EDX,DWORD PTR DS:[403010]
004010BB  |. FF35 20304000  PUSH DWORD PTR DS:[403020]
004010C1  |. FF35 1C304000  PUSH DWORD PTR DS:[40301C]
004010C7  |. FF35 18304000  PUSH DWORD PTR DS:[403018]
004010CD  |. FF35 14304000  PUSH DWORD PTR DS:[403014]
004010D3  |. 52             PUSH EDX
004010D4  |. 50             PUSH EAX
004010D5  |. FF35 08304000  PUSH DWORD PTR DS:[403008]
004010DB  |. FF35 04304000  PUSH DWORD PTR DS:[403004]
004010E1  |. FF35 00304000  PUSH DWORD PTR DS:[403000]
004010E7  |. E8 14FFFFFF    CALL test.00401000
004010EC  |. B9 04000000    MOV ECX,4
004010F1  |. 99             CDQ
004010F2  |. F7F1           DIV ECX


Well Microsoft, here's another nice mess you've gotten us into.

FORTRANS

Quote from: turboscrew on December 29, 2013, 06:13:09 AM
And it looks like ASSUME DS:segment really tells the assembler what kind of code to emit for data accesses: like far + segment or near.

Hi,

   Right.  ASSUME tells the assembler what to expect it to use
when accessing a symbol (label).  See the following example.


       7 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       8 0000 DATASEG SEGMENT
       9 0000  41 6D 70 68 69 62 69 FROG    DB      'Amphibian$'
      10       61 6E 24
      11 000A DATASEG ENDS
      12 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      13 0000 OTHERSG SEGMENT
      14 0000  52 65 70 74 69 6C 65 GILA    DB      'Reptile'
      15 0007 OTHERSG ENDS
      16 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      17 0000 CODE    SEGMENT PUBLIC 'CODE'
      18         ASSUME  CS:CODE
      19
      20 0000 Start   PROC
      21 0000  B8 ---- R         MOV     AX,SEG DATASEG
      22 0003  8E D8         MOV     DS,AX
      23 0005  B8 ---- R         MOV     AX,SEG OTHERSG
      24 0008  8E C0         MOV     ES,AX
      25         ASSUME  CS:CODE, DS:DATASEG, ES:OTHERSG
      26 000A  A0 0000 R         MOV     AL,[FROG]       ; Put 'A' into AL.
      27 000D  26: 8A 1E 0000 R         MOV     BL,[GILA]       ; Put 'R' into BL.


   Note that 26H is the ES segment override prefix.  (You may
also note that AL is an accumulator register, and has a special
form of the MOV instruction.)

Regards,

Steve N.

turboscrew

Truckload of thanks, guys.
I guess I finally got a good grip of those forever-bothered the things that have bothered me "forever".