PRODUCT : TURBO BASIC NUMBER : 430 VERSION : 1.1 OS : PC-DOS DATE : APRIL 4, 1989 PAGE : 1/3 TITLE : PASSING STRINGS VIA A CALL ABSOLUTE STATEMENT TO AN ASSEMBLY LANGUAGE PROCEDURE This program demonstrates how to pass strings, using the CALL ABSOLUTE statement, to an assembly language procedure. 'TESTCAPS.BAS invokes CAPS.COM A = EndMem - 100 'Reserve space for CAPS.ASM (trailer-header = 41h) MEMSET A 'Reserve an area at the top of memory for the subroutine 'Compute the 16-bit segment from the 32-bit start address Segment = fix(A/16) 'Compute the 16-bit offset from the 32-bit address Ucase = A - (Segment * 16) DEF SEG = Segment BLOAD "CAPS.COM",Ucase DEF SEG CLS A$ = "Hello World !" B$ = SPACE$(LEN(A$)) 'Call to translate A$ to uppercase and store 'in B$ S1seg% = VARSEG(A$) 'Store the segment address of A$ in S1seg% S1ofs% = VARPTR(A$) 'Store the address of A$ in S1seg% S2seg% = VARSEG(B$) 'Store the address of B$ in S1seg% S2ofs% = VARPTR(B$) 'Store the address of B$ in S1seg% DEF SEG = Segment CALL ABSOLUTE Ucase(S1seg%,S1ofs%,S2seg%,S2ofs%) DEF SEG PRINT "[";A$;"]" PRINT "[";B$;"]" END ;CAPS.ASM ;Translate the first parameter to uppercase and store in second ;parameter. PRODUCT : TURBO BASIC NUMBER : 430 VERSION : 1.1 OS : PC-DOS DATE : APRIL 4, 1989 PAGE : 2/3 TITLE : PASSING STRINGS VIA A CALL ABSOLUTE STATEMENT TO AN ASSEMBLY LANGUAGE PROCEDURE ;CAPS.COM is called from Turbo Basic: ; ; 'reserve space for caps.asm (trailer -header = 41h 1h) ; A= ENDMEM - 100 ; MEMSET A ; ; 'Convert first$ to uppercase and store in second$: ; S1seg% = VARSEG(First$) ; S1ofs% = VARPTR(First$) ; S2seg% = VARSEG(Second$) ; S2ofs% = VARPTR(Second$) ; Segment = fix(A/16) ; Ucase = A - (Segment * 16) ; DEF SEG = Segment ; CALL ABSOLUTE Ucase(S1seg%,S1ofs%,S2seg%,S2ofs%) ; DEF SEG ; ; Assembled with Microsoft's Macro Assembler 4.00 ; bsave equ 0fdh aaa segment para ;BLOAD header db bsave dw 0,0 dw trailer-header aaa ends cseg segment byte public 'code' assume cs:cseg,ds:cseg header equ $ caps proc far push bp push ds ;save ds and es too because we must ;now push es ;keep track of string's segment mov ax,ds ;save ds in ax temporarily mov bp,sp mov si,[bp+0eh] ;ofs of int var which holds 1ststr ;desc ofs mov si,[si] ;SI=offset of 1st string descriptor mov bx,[bp+10h] ;ofs of int var which holds 1st str ;desc seg mov ds,[bx] ;DS = segment of 1st string descriptor mov cx,[si] ;get length of 1st string from descriptor and ch,80h ;strip off upper reserved bit of length PRODUCT : TURBO BASIC NUMBER : 430 VERSION : 1.1 OS : PC-DOS DATE : APRIL 4, 1989 PAGE : 3/3 TITLE : PASSING STRINGS VIA A CALL ABSOLUTE STATEMENT TO AN ASSEMBLY LANGUAGE PROCEDURE jcxz s2 ;done if string length = 0 mov si,[si+2] ;get offset of 1st string in string ;segment mov ds,ax ;get original DS value back mov ax,ds:0 ;AX = current string segment value (from ;DS:0) mov di,[bp+0ah] ;ofs of int var which holds 2nd str desc ;ofs mov di,[di] ;DI = offset of 2nd string descriptor mov bx,[bp+0ch] ;ofs of int var which holds 2nd str desc ;seg mov es,[bx] ;ES = segment of 2nd string descriptor mov di,es:[di+2];get offset of 2nd string in string ;segment mov ds,ax ;DS = current string segment value (from ;DS:0) mov es,ax ;put it in ES for later ; ; At this point, DS:SI points to the start of first$, CX ; contains the length of first$, and ES:DI points to the ; start of second$ ; S0: lodsb ;get character from DS:SI (first$) cmp al,'a' jl s1 cmp al,'z' jg s1 and al,223 S1: stosb loop S0 ;put character in ES:DI (second$) S2: mov sp,bp pop es ;restore ES and DS too pop ds pop bp ret 8 caps endp trailer equ $ cseg ends end