Chapter16 A program with no include files TITLE Simple (Simple.asm) .model small,stdcall .stack 100h ;;256 bytes of stack space for this or other prgrams to use .data msg1 db "simple assembly example",0dh,0ah,'$' .code main PROC mov ax,@data mov ds,ax mov dx,offset msg1 mov ah,9 int 21h mov ax,4c00h int 21h main ENDP END main Running simple without batch file: DOS screen C:\MASM615>ml simple.asm Microsoft (R) Macro Assembler Version 6.15.8803 Copyright (C) Microsoft Corp 1981-2000. All rights reserved. Assembling: simple.asm Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994 Copyright (C) Microsoft Corp 1984-1993. All rights reserved. Object Modules [.obj]: simple.obj Run File [simple.exe]: "simple.exe" List File [nul.map]: NUL Libraries [.lib]: Definitions File [nul.def]: C:\MASM615>simple simple assembly example C:\MASM615> Invoking the assembler and linker separately • By invoking the assembler (ml.exe) using masm.exe and the linker (link) separately, you can define the name of the exe and other output files instead of using default naming. • You can also link multiple modules into a single executable using: Link modA ModB modC • Where the first file named will be the “main” Running simple without batch file: DOS screen, version 2… C:\MASM615>masm simple Microsoft (R) MASM Compatibility Driver Copyright (C) Microsoft Corp 1993. All rights reserved. Invoking: ML.EXE /I. /Zm /c simple.asm Microsoft (R) Macro Assembler Version 6.15.8803 Copyright (C) Microsoft Corp 1981-2000. All rights reserved. Assembling: simple.asm C:\MASM615>link simple Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994 Copyright (C) Microsoft Corp 1984-1993. All rights reserved. Run File [simple.exe]: List File [nul.map]: Libraries [.lib]: Definitions File [nul.def]: C:\MASM615>simple simple assembly example Explicit segment definition: running explicit C:\MASM615>masm explicit Microsoft (R) MASM Compatibility Driver Copyright (C) Microsoft Corp 1993. All rights reserved. Invoking: ML.EXE /I. /Zm /c explicit.asm Microsoft (R) Macro Assembler Version 6.15.8803 Copyright (C) Microsoft Corp 1981-2000. All rights reserved. Assembling: explicit.asm C:\MASM615> C:\MASM615>link explicit Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994 Copyright (C) Microsoft Corp 1984-1993. All rights reserved. Run File [explicit.exe]: List File [nul.map]: Libraries [.lib]: Definitions File [nul.def]: C:\MASM615>explicit simple assembly example Explicit.asm TITLE Explicit (Explicit.asm) CSEG SEGMENT 'CODE' ASSUME CS:CSEG,DS:DSEG,SS:SSEG main PROC mov ax,DSEG mov ds,ax mov dx,offset msg1 mov ah,9 int 21h mov ax,4c00h int 21h main ENDP CSEG ENDS SSEG SEGMENT PARA STACK 'STACK' byte 100 dup(0) SSEG ENDS DSEG SEGMENT 'DATA' msg1 db "simple assembly example",0dh,0ah,'$' DSEG ENDS END main About ASSUME • The assume directive does not point registers (ds, es) where they are supposed to go. The programmer must still do that. • It tells the assembler to assemble code assuming that’s where the segments will be. Multiple code segments • A call to a proc in a different code segment is a far call, requiring both cs and ip be saved (pushed), changed to point to the called proc, then recovered (popped). Of course the system does the pushing and popping. • The programmer must define procs as far when appropriate. Multcode example from text: note far proc TITLE Multiple Code Segments (MultCode.asm) .model small,stdcall .stack 100h WriteString PROTO .data msg1 db "First Message",0dh,0ah,0 msg2 db "Second Message",0dh,0ah,"$" .code main PROC mov ax,@data mov ds,ax mov dx,OFFSET msg1 call WriteString ; NEAR call call Display ; FAR call .exit main ENDP .code OtherCode Display PROC FAR mov ah,9 mov dx,offset msg2 int 21h ret Display ENDP END main Assemble and run… C:\MASM615>make16 multcode Assembling: multcode.asm Volume in drive C has no label. Volume Serial Number is 07D2-0208 Directory of C:\masm615 11/29/2006 01:09 PM 457 MultCode.asm 11/29/2006 01:11 PM 714 multcode.obj 11/29/2006 01:11 PM 2,597 multcode.lst 11/29/2006 01:11 PM 5,948 multcode.exe 4 File(s) 9,716 bytes 0 Dir(s) 4,028,284,928 bytes free Press any key to continue . . . C:\MASM615>multcode First Message Second Message About small model • When you use model small the assembler automatically defines DGROUP for near data, accessible via DS or SS. .DATA and .DATA? Both create near data segments, placed in DGROUP • .FARDATA and .FARADATA? Create far data segments in the small memory model. • DS (or ES) must point to a sement before a variable in the segment can be accessed. • The segment defined by .CODE in the small model is named _TEXT. • You can view the naming conventions by examining a lst file. Here’s part of the lst for multcode Segments and Groups: Name DGROUP . . . . . . . . . . . . . _DATA . . . . . . . . . . . . . STACK . . . . . . . . . . . . . OtherCode . . . . . . . . . . . _TEXT . . . . . . . . . . . . . Size Length Align Combine Class GROUP 16 Bit 16 Bit 16 Bit 16 Bit 0021 0100 0008 0014 Word Para Word Word Public 'DATA' Stack 'STACK' Public 'CODE' Public 'CODE' Procedures, parameters and locals: Name Display . . . . . . . . . . . . Public STDCALL WriteString . . . . . . . . . . main . . . . . . . . . . . . . . STDCALL Type Value Attr P Far 0000 OtherCode Length= 0008 P Near P Near 0000 0000 Length= 0000 External STDCALL _TEXT Length= 0014 Public Modified Multdata from text: multiple data segments TITLE Multiple Data Segments (MultData.asm) ; This program shows how to explicitly declare ; multiple data segments. ; Last update: 2/1/02 cseg SEGMENT 'CODE' ASSUME cs:cseg, ds:data1, ss:mystack main PROC mov ax,data1 ; point DS to data1 segment mov ds,ax mov ax,seg val2 ; point ES to data2 segment mov es,ax mov ah,2 mov dx,val1 ; requires ASSUME for DS int 21h mov dx,es:val2 ; ASSUME not required int 21h mov ax,4C00h ; return to MS-DOS int 21h main ENDP cseg ENDS data1 SEGMENT 'DATA' ; specify class type val1 dw 65;;;letter 'A; data1 ENDS data2 SEGMENT 'DATA' val2 dw 57;;;digit char 9 data2 ENDS mystack SEGMENT para STACK 'STACK' BYTE 100h dup('S') mystack ENDS END main My version has output (A9) C:\MASM615>make16 multdata Assembling: multdata.asm Volume in drive C has no label. Volume Serial Number is 07D2-0208 Directory of C:\masm615 11/29/2006 01:31 PM 830 MultData.asm 11/29/2006 01:32 PM 533 multdata.obj 11/29/2006 01:32 PM 1,964 multdata.exe 11/29/2006 01:32 PM 2,297 multdata.lst 4 File(s) 5,624 bytes 0 Dir(s) 4,027,875,328 bytes free Press any key to continue . . . C:\MASM615>multdata A9 Segment overrides • If you plan to access a value (like [bx] or [si]) which has a default segment, via a different segment, you must use an override. • Default segment assignments include: es:di, ds:si, ds:bx, cs:ip, ss:sp Segment overrides • You can access a variable without an assume by using a segment override, that is, explicitly providing a segment with an offset. • This has the form someseg:someofs Programs with multiple modules • One module (B) may define code or data symbols used in another module (A). • In order to assemble module A the assembler needs to know what type the symbols will have (near, far, byte, word, dword, etc). An EXTERN directive assures the assembler the symbols are defined elsewhere. (It is the programmer’s responsibility to do this). Programs with multiple modules • Module B needs to be assembled so that some symbols are made available at link time so that their addresses can be resolved by the linker. • The PUBLIC directive indicates that a variable defined in this module may be needed in another module. • It is NOT an error if a variable “declared” PUBLIC is not used elsewhere, but it is an error if a variable declared “EXTERN” is NOT defined in another module and declared “PUBLIC” there. Programs with multiple modules • Different directives tell the assembler how to combine segments with the same name. • COMMON means put them at the same start address (over each other) • PUBLIC means combine into a single segment • PRIVATE is the default, meaning segments with the same name in different modules will NOT be combined into a single segment. • ALIGN tells the assembler on what address boundary to begin. PARA means paragraph (address ends in 0000). Higher align types mean faster variable access. Programs may have multiple segments which are combined TITLE Segment Example (submodule, SEG2A.ASM) PUBLIC subroutine_1, var2 cseg SEGMENT BYTE PUBLIC 'CODE' ASSUME cs:cseg, ds:dseg subroutine_1 PROC ; called from MAIN mov ah,9 mov dx,OFFSET msg int 21h ret subroutine_1 ENDP cseg ENDS dseg SEGMENT WORD PUBLIC 'DATA' var2 WORD 2000h ; accessed by MAIN msg BYTE 'Now in Subroutine_1' BYTE 0Dh,0Ah,'$' dseg ENDS END Seg2 from text TITLE Segment Example (main module, Seg2.asm) EXTRN var2:WORD subroutine_1 PROTO cseg SEGMENT BYTE PUBLIC 'CODE' ASSUME cs:cseg,ds:dseg, ss:sseg main PROC mov ax,dseg ; initialize DS mov ds,ax mov ax,var1 ; local variable mov bx,var2 ; external variable call subroutine_1 ; external procedure mov ax,4C00h ; exit to OS int 21h main ENDP cseg ENDS dseg SEGMENT WORD PUBLIC 'DATA' ; local data segment var1 WORD 1000h dseg ends sseg SEGMENT STACK 'STACK' ; stack segment BYTE 100h dup('S') sseg ENDS END main Assemble each module separately C:\MASM615\EXAMPLES\CH16>masm seg2.asm Microsoft (R) MASM Compatibility Driver Copyright (C) Microsoft Corp 1993. All rights reserved. Invoking: ML.EXE /I. /Zm /c /Ta seg2.asm Microsoft (R) Macro Assembler Version 6.15.8803 Copyright (C) Microsoft Corp 1981-2000. All rights reserved. Assembling: seg2.asm MASM : fatal error A1000: cannot open file : seg2.asm C:\MASM615\EXAMPLES\CH16>cd seg2 C:\MASM615\EXAMPLES\CH16\SEG2>masm seg2 Microsoft (R) MASM Compatibility Driver Copyright (C) Microsoft Corp 1993. All rights reserved. Invoking: ML.EXE /I. /Zm /c seg2.asm Microsoft (R) Macro Assembler Version 6.15.8803 Copyright (C) Microsoft Corp 1981-2000. All rights reserved. Assembling: seg2.asm Note how to link (list of modules) with main first C:\MASM615\EXAMPLES\CH16\SEG2>link seg2 seg2a Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 199 Copyright (C) Microsoft Corp 1984-1993. All rights reserved. Run File [seg2.exe]: List File [nul.map]: Libraries [.lib]: Definitions File [nul.def]: C:\MASM615\EXAMPLES\CH16\SEG2>seg2 Now in Subroutine_1 C:\MASM615\EXAMPLES\CH16\SEG2> COM and EXE etc C:\>blah • Command.COM first checks a command line instruction to see if it is internal (like DIR). • After this, it looks for a matching exe file (blah.exe). • If this fails, it looks for a com file (blah.com) • Failing to find one it searches for a batch file. (blah.bat) • After this it searches directories in the path for the program. Com vs exe • A com is a binary file. It is loaded by ms-dos at the lowest available memory location and a PSP (program segment prefix) is created at offset 0. Code, data and stack are in the same physical & logical segment, which may be up to 64K minus the psp. COM programs use the tiny memory model. • All the segment registers are set to the psp address. The stack area is allocated after the code and any data. • You may not explicitly declare a stack segment Com vs exe • Com files must start at 100h and so require code: Org 100h • Org instruction tells the assembler what address to use. Using org, for example, you can “re-assemble” over previous assembly by org-ing back to a previous address. Hellocom from text TITLE Hello Program in COM format (HelloCom.asm) .model tiny .code org 100h ; must be before main main PROC mov ah,9 mov dx,OFFSET hello_message int 21h mov ax,4C00h int 21h main ENDP hello_message BYTE 'Hello, world!',0dh,0ah,'$' END main Creating .com instead of .exe • Link with /t parameter to create a com file. • there is also a program around named exe2bin which will convert exe to com Assembling & running a com file C:\MASM615>masm hellocom Microsoft (R) MASM Compatibility Driver Copyright (C) Microsoft Corp 1993. All rights reserved. Invoking: ML.EXE /I. /Zm /c hellocom.asm Microsoft (R) Macro Assembler Version 6.15.8803 Copyright (C) Microsoft Corp 1981-2000. All rights reserved. Assembling: hellocom.asm C:\MASM615>link /t hellocom Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994 Copyright (C) Microsoft Corp 1984-1993. All rights reserved. Run File [hellocom.com]: List File [nul.map]: Libraries [.lib]: Definitions File [nul.def]: LINK : warning L4045: name of output file is 'hellocom.com' C:\MASM615>hellocom Hello, world! interrupts • You can customize interrupt handling for DOS and BIOS by installing you own handlers • The hardware was designed with this possibility of tinkering, or customizing. • You can replace any service routine with your own. Interrupt handlers • You might want your own program to handle a special key-press • A default handler could be replaced by one with more service. For example, the clock tick handler which does nothing, could update a digital or analog clock display on the screen. • Buffering could be provided for the pc’s asynchronous communication handler (int 14h) The vector table: pg 598 • The vector table is in the first K of RAM, locations 0:0 to 0:03FF • The entries in the table, called “interrupt vectors” are 32 bit seg:ofs values that point to existing service routines. • The specific values vary from one computer to another due to different BIOS or DOS versions The vector table • The interrupt vectors correspond to interrupt numbers • The address of int 0 handler (div by 0) is 02C1:5186h. • The offset for a vector can be found by multiplying the interrupt number by 4 (shl 2) interrupts • You can execute an interrupt by performing an int XXX • This is called a software interrupt • A hardware interrupt may also call the handler (timer, ports, keyboard and so on all send signals to the PIC). interrupts • A hardware interrupt is generated by the Intel 8259 PIC which signals the cpu to suspend execution of the current program and execute an interrupt service handler. • Note that the current program stack is used to save the return address. • The instructions CLI clear interrupt flag (disable) and STI (enable) set interrupt flag enable a program to temporarily disable/re-enable interrupts if sensitive operations are underway, like changing the value of a segment register. IRQ • Interrupts have specific request levels, given in text table pg 599. • A low-level interrupt can’t break into a high level one. A custom handler: ctrl break TITLE Control-Break Handler (Ctrlbrk.asm) ; This program installs its own Ctrl-Break handler and ; prevents the user from using Ctrl-Break (or Ctrl-C) ; to halt the program. The program inputs and echoes ; keystrokes until the Esc key is pressed. ; Last update: 2/1/02 INCLUDE Irvine16.inc .data breakMsg BYTE "BREAK",0 msg BYTE "Ctrl-Break demonstration." BYTE 0dh,0ah BYTE "This program disables Ctrl-Break (Ctrl-C). Press any" BYTE 0dh,0ah BYTE "keys to continue, or press ESC to end the program." BYTE 0dh,0ah,0 ctrl break continued .code main PROC mov ax,@data mov ds,ax mov dx,OFFSET msg ; display greeting message call Writestring install_handler: push ds ; save DS mov ax,@code ; initialize DS mov ds,ax mov ah,25h ; set interrupt vector mov al,23h ; for interrupt 23h mov dx,OFFSET break_handler int 21h pop ds ; restore DS L1: mov ah,1 int 21h cmp al,1Bh jnz L1 ; wait for a key, echo it ; ESC pressed? ; no: continue exit main ENDP ; The following procedure executes when ; Ctrl-Break (Ctrl-C) is pressed. break_handler PROC push ax push dx mov dx,OFFSET breakMsg call Writestring pop dx pop ax iret break_handler ENDP END main Tsr programs • Terminate-stay-resident Text example TITLE Reset-Disabling program (No_Reset.asm) ; This program disables the usual DOS reset command ; (Ctrl-Alt-Del), by intercepting the INT 9 keyboard ; hardware interrupt. It checks the shift status bits ; in the MS-DOS keyboard flag and changes any Ctrl-Alt-Del ; to Alt-Del. The computer can only be rebooted by ; typing Ctrl+Alt+Right shift+Del. Assemble, link, ; and convert to a COM program by including the /T ; command on the Microsoft LINK command line. ; Last update: 10/12/01 .model tiny .code rt_shift EQU 01h ctrl_key EQU 04h alt_key EQU 08h del_key EQU 53h kybd_port EQU 60h ORG 100h start: jmp setup ; Right shift key: bit 0 ; CTRL key: bit 2 ; ALT key: bit 3 ; scan code for DEL key ; keyboard input port ; this is a COM program ; jump to TSR installation continued ; Memory-resident code begins here int9_handler PROC FAR sti ; enable hardware interrupts pushf ; save regs & flags push es push ax push di ; Point ES:DI to the DOS keyboard flag byte: L1: mov ax,40h ; DOS data segment is at 40h mov es,ax mov di,17h ; location of keyboard flag mov ah,es:[di] ; copy keyboard flag into AH ; Test for the CTRL and ALT keys: L2: test ah,ctrl_key jz L5 test ah,alt_key jz L5 ; CTRL key held down? ; no: exit ; ALT key held down? ; no: exit More… ; Test for the DEL and Right-shift keys: L3: in al,kybd_port ; read keyboard port cmp al,del_key ; DEL key pressed? jne L5 ; no: exit test ah,rt_shift ; right shift key pressed? jnz L5 ; yes: allow system reset L4: and ah,NOT ctrl_key mov es:[di],ah ; no: turn off bit for CTRL ; store keyboard_flag L5: pop pop pop popf jmp di ax es ; restore regs & flags cs:[old_interrupt9] ; jump to INT 9 routine old_interrupt9 DWORD ? int9_handler ENDP end_ISR label BYTE And a bit more… ; --------------- (end of TSR program) -----------------; Save a copy of the original INT 9 vector, and set up ; the address of our program as the new vector. Terminate ; this program and leave the int9_handler procedure in memory. setup: mov ax,3509h int 21h mov word ptr old_interrupt9,bx mov word ptr old_interrupt9+2,es mov ax,2509h mov dx,offset int9_handler int 21h ; get INT 9 vector ; save INT 9 vector ; set interrupt vector, INT 9 mov ax,3100h ; terminate and stay resident mov dx,OFFSET end_ISR ; point to end of resident code shr dx,4 ; multiply by 16 inc dx ; round upward to next paragraph int 21h ; execute MS-DOS function END start