This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
"H.J. Lu" <hjl.tools@gmail.com> writes: > Hi Jan, > > Do you have testcases? netboot fails with: runtime.S86: Assembler messages: runtime.S86:388: Error: suffix or operands invalid for `jmp' runtime.S86:393: Error: suffix or operands invalid for `jmp' runtime.S86:398: Error: suffix or operands invalid for `jmp' Andreas
/* * runtime.S86 - MGL runtime module * * Copyright (C) 2003-2007 Gero Kuhlmann <gero@gkminix.han.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: runtime.S86,v 1.13 2007/01/06 18:31:38 gkminix Exp $ * *==================================================================== */ #include "rtcommon.i86" #include <pxe/general.i86> .file __FILE__ .line __LINE__ /* *==================================================================== * * Definitions local to this module */ #define INT_0_OFS (0 * 4) /* offset to interrupt vector 0 */ #define INT_4_OFS (4 * 4) /* offset to interrupt vector 4 */ #define INT_5_OFS (5 * 4) /* offset to interrupt vector 5 */ .line __LINE__ /* *==================================================================== * * Define the text segment. This segment can start at any offset depending * on the loader used. The mknbi-mgl bootrom loader loads this program * at offset 0, while DOS loads this program at offset 0x0100. */ .text .extern prcrlf # externals from runtime library .extern prnstr .extern prnnum .extern keycheck .extern keyget .extern brk .extern sbrk .extern initpxe .extern _init_bootp # external initialization routines .extern _init_console .extern _init_net .extern _rtint_raise # external exception handler .global _start # global routines .global _rtint_exit .global _rtint_error .global _rtint_chkstk _start: jmp start /* *==================================================================== * * The header of the runtime module serves two purposes: first it gives * the compiler certain information about the size and location of various * parts of the runtime module, and secondly the compiler will give some * information back like the size of the produced code, etc. */ .org RT_DATAOFS rtinfo: .word rtid # offset to ID string .long 0 # total load size of program .word __text_end # end of runtime text segment .word __data_end # end of runtime data segment .word __bss_end # end of runtime BSS segment .word 0 # end of constant data .word 0 # end of variable data .word __initext_end # offset to data segment .word exptable # offset to debugging data/export table .word 0 # start address .word RTSTK_DEFAULT # default stack size newds: .word 0 # new data segment oldi0: .long 0 # old interrupt vectors oldi4: .long 0 oldi5: .long 0 rtid: .asciz RT_IDSTRING # runtime ID string /* *==================================================================== * * Here the actual game starts. This program gets called by a loader * which passes the pointer to an information structure in ES:SI. * In this program we can be sure to run on a 386+ processor. */ start: push ds push es # save the BOOTP record pointer push si call 1f # compute code offset 1: pop ax sub ax,offset 1b mov bx,ax # save code offset in BX mov dx,cs # convert code segment so that shr ax,4 # it starts at a zero offset add dx,ax # save code segment in DX mov ax,cs:rtdata_dataofs[bx + rtinfo] shr ax,4 add ax,dx mov ds,ax mov es,ax mov cs:[bx + newds],ax # save it for later cld xor ax,ax mov di,cs:rtdata_constend[bx + rtinfo] mov cx,cs:rtdata_varend[bx + rtinfo] sub cx,di inc cx # clear variable data area shr cx,1 rep stosw std mov di,cs:rtdata_constend[bx + rtinfo] mov cx,di dec di sub cx,cs:rtdata_bssend[bx + rtinfo] mov si,cs:rtdata_dataend[bx + rtinfo] add si,cx dec si # copy constant data area into rep movsb # proper position cld mov di,cs:rtdata_dataend[bx + rtinfo] mov cx,cs:rtdata_bssend[bx + rtinfo] sub cx,di rep stosb # clear BSS segment pop dword ptr [infoptr] # save the info record pointer push dx # push new code segment value mov ax,offset 2f # change into new code segment push ax lret 2: cli mov word ptr [oldstack + 0],sp mov word ptr [oldstack + 2],ss mov ax,ds # set new stack mov ss,ax mov sp,0xFFFE mov word ptr [stktop],sp # save top of stack pointer sti nop # necessary for some debuggers /* * Check for PXE support */ push es les bx,[infoptr] les bx,es:rtload_pxe[bx] call initpxe # initialize PXE support pop es or ax,ax jnz 4f # check if we have PXE installed inc byte ptr [_havepxe] /* * Check for flags passed to us by the runtime loader. If the trap flag * has not been set, disable all INT3 instructions. */ 4: push es les bx,[infoptr] mov eax,es:rtload_bootp[bx] mov [_btpptr],eax mov ax,es:rtload_bsize[bx] mov [_btplen],ax mov ax,es:rtload_flags[bx] pop es test ax,RTFLAG_LOAD setnz byte ptr [_canload] test ax,RTFLAG_RUN setnz byte ptr [_canrun] test ax,RTFLAG_BOOTP setnz byte ptr [_canchange] test ax,RTFLAG_TRAP jz 3f jmp 0f .align 8 .ascii "trapadr$" # string to find the trap address in # the runtime binary trapaddr: .word 0 # address where to trap into the # debugger 0: int3 # trap into debugger to allow changing nop # the trap address mov si,offset traplist 1: mov bx,cs:[si] # scan through list of int3 or bx,bx # instructions jz 3f mov byte ptr cs:[bx],0xCC # replace it with a INT3 instruction add si,2 jmp 1b traplist: .word trap1 # list of int3 instruction .word trap2 # addresses .word trap3 .word 0 /* * This is required for GCC, which may use EBP for other purposes than * a stack pointer. */ 3: xor ebp,ebp /* * Setup all interrupt vectors required for the user program */ cli push es xor ax,ax mov es,ax mov eax,dword ptr es:[INT_0_OFS] mov dword ptr cs:[oldi0],eax mov eax,dword ptr es:[INT_4_OFS] mov dword ptr cs:[oldi4],eax mov eax,dword ptr es:[INT_5_OFS] mov dword ptr cs:[oldi5],eax mov word ptr es:[INT_0_OFS + 0],cs mov word ptr es:[INT_4_OFS + 0],cs mov word ptr es:[INT_5_OFS + 0],cs mov word ptr es:[INT_0_OFS + 2],offset rtint0 mov word ptr es:[INT_4_OFS + 2],offset rtint4 mov word ptr es:[INT_5_OFS + 2],offset rtint5 pop es sti /* * Set the stack size and the correct beginning of the heap */ mov ax,cs:rtdata_stksize[rtinfo] mov [stksiz],ax mov ax,cs:rtdata_varend[rtinfo] call brk # set new heap pointer cmp ax,-1 # check that we have enough memory jne 6f 5: mov ax,ENOMEMORY + NOUSER_ERROR_FLAG call _rtint_raise 6: mov ax,[stktop] sub ax,[stksiz] # compute stack base jc 5b mov [stkbase],ax /* * Call module initialization routines. Note that the network * initialization routine has to come first! */ call _init_net call _init_bootp call _init_console trap1: nop # gets replaced by int3 /* * Now call the user program. It should never return except for a * runtime error. The normal program termination is via the "load" * system call. Note that the user program expects the direction * flag cleared all the time. */ cld mov ax,word ptr cs:rtdata_start[rtinfo] call ax mov bx,RTERROR_ABORT # prepare return value /* * Call all cleanup routines */ doexit: trap2: nop # gets replaced by int3 xor ax,ax mov [rtaddr],ax xchg ax,[_atexit] # check if cleanup routine defined or ax,ax jz 7f xchg ax,bx movzx32 eax,ax call bx # call daisy-chained cleanup routines mov bx,ax /* * Restore all interrupt vectors */ 7: cli push es xor ax,ax mov es,ax mov eax,cs:dword ptr [oldi0] mov dword ptr es:[INT_0_OFS],eax mov eax,cs:dword ptr [oldi4] mov dword ptr es:[INT_4_OFS],eax mov eax,cs:dword ptr [oldi5] mov dword ptr es:[INT_5_OFS],eax pop es sti /* * After restoring the stack, return to the caller via a far return */ 8: cli mov ss,word ptr [oldstack + 2] mov sp,word ptr [oldstack + 0] sti # restore stack and return to mov ax,bx # caller pop ds lret /* *==================================================================== * * Handle runtime errors * Input: none * Output: none * Registers changed: all (routine doesnt return) */ rtint0: push si mov si,EDIVZERO # division by zero jmp 1f rtint4: push si mov si,EOVERFLOW # integer overflow jmp 1f rtint5: push si mov si,EOUTOFBOUNDS # bounds error 1: push ax push bp mov bp,sp mov ax,cs cmp ax,[bp + 8] # check if the error was produced by pop bp # our own program pop ax je 6f cmp si,EDIVZERO jne 3f pop si # call old interrupt 0 jmp dword ptr cs:[oldi0] 3: cmp si,EOVERFLOW jne 4f pop si # call old interrupt 4 jmp dword ptr cs:[oldi4] 4: cmp si,EOUTOFBOUNDS jne 6f pop si # call old interrupt 5 jmp dword ptr cs:[oldi5] /* * Process a runtime error in our own program */ 6: sti pop ax mov ax,cs:[newds] # this is just for safety mov ds,ax mov es,ax mov ax,si jmp _rtint_raise # raise an exception /* *==================================================================== * * Check the stack pointer and set the runtime address. This routine * gets called by all routines callable from the user program. * Input: AX - Required stack size * Output: None * Registers changed: None */ _rtint_chkstk: push bp push ax mov bp,sp mov ax,[bp + 6] # save return address sub ax,3 mov [rtaddr],ax sub bp,[bp + 0] jc 1f cmp bp,[stkbase] # check that we have enough stack ja 3f # space 1: xor ax,ax # determine top of heap space call sbrk cmp ax,bp # if the stack already grew into the mov ax,ESTKOVERFLOW # heap, the user exception info might jb 2f # be destroyed, so we dont allow scan- add ax,NOUSER_ERROR_FLAG # ning the user handlers in that case. 2: call _rtint_raise 3: mov ax,[rtaddr] cmp ax,cs:[trapaddr] # check if we have to call the jne 9f # debugger trap trap3: nop # gets replaced by int3 9: pop ax pop bp ret _rtproc_chkstk: push bp mov bp,sp mov ax,[bp + 4] # get required stack size pop bp call _rtint_chkstk # call checking routine ret 2 /* *==================================================================== * * Terminate the program * Input: AX - Return code * Output: None * Registers changed: all (routine does not return) */ _rtint_exit: pop bx # discard return address mov bx,ax jmp doexit # terminate the program _rtproc_exit: pop bx # discard return address mov bx,RTERROR_ABORT jmp doexit # terminate the program /* *==================================================================== * * Print a runtime error * Input: AX - Pointer to error string * Output: None * Registers changed: all (routine does not return) */ _rtint_error: pop bx # discard return address push ax mov si,offset rterr call prnstr # print error message pop si call prnstr cld mov si,[debugptr] or si,si # check if we have a debugging info jz 8f # table mov bx,[rtaddr] or bx,bx # check if we have a valid address jz 8f xor cx,cx 2: lodsw # scan through the debug table to or ax,ax # find the address jz 7f cmp ax,bx ja 7f lodsw mov cx,ax # remember last line number jmp 2b 7: jcxz 8f # check if we found a line number mov si,offset linerr call prnstr movzx32 eax,cx # print the line number call prnnum 8: call prcrlf mov si,offset keyerr # print "keypress" message call prnstr call keycheck # clear keyboard buffer call keyget # wait for a key press 9: mov bx,RTERROR_ABORT # indicate error return jmp doexit # terminate the program /* *==================================================================== * * Export table */ .section .initext exptable: /* * Version information */ .byte RTEXP_VERSION # type of export record .byte VALTYPE_NUM # version information is string type .word RTIF_VERSION .word 0 .asciz "Interface Version" # name of record /* * "exit" routine */ .byte RTEXP_PROC # type of export record .byte VALTYPE_NONE # return type .word _rtproc_exit # offset to routine .word 0 # number of arguments .asciz "exit" # name of routine /* * "chkstk" routine */ .byte RTEXP_PROC # type of export record .byte VALTYPE_NONE # return type .word _rtproc_chkstk # offset to routine .word 1 # number of arguments .asciz "chkstk" # name of routine .byte VALTYPE_NUM # 1st arg: number .byte VALTYPE_NONE # 1st arg: passed by value /* *==================================================================== * * Data area */ _rodata /* Copyright message */ cpyrgt: .ascii "MGL runtime module " .ascii VERSION .byte 0x0D, 0x0A .ascii COPYRIGHT .byte 0x0D, 0x0A .byte 0x0D, 0x0A .byte 0 /* Error messages */ rterr: .asciz "Runtime error: " linerr: .asciz " at line " keyerr: .asciz "Press any key to continue" /* *==================================================================== * * Data segment */ .data .extern stksiz # stack size for i386 library /* *==================================================================== * * BSS segment */ .bss /* Global variables for the runtime module */ .global _atexit .global _btpptr .global _btplen .global _canload .global _canrun .global _canchange .global _havepxe .lcomm _atexit,2 # pointer to first cleanup routine .lcomm _btpptr,4 # pointer to bootrom BOOTP buffer .lcomm _btplen,2 # size of bootrom BOOTP buffer .lcomm _canload,1 # flag if we accept RTERROR_LOAD .lcomm _canrun,1 # flag if we accept RTERROR_RUN .lcomm _canchange,1 # flag if we accept BOOTP changes .lcomm _havepxe,1 # flag if we have PXE support /* Local variables */ .global stktop # required for i386 library .align 2 .lcomm rtaddr,2 # current runtime address .lcomm infoptr,4 # pointer to info record .lcomm stktop,2 # pointer to top of stack .lcomm stkbase,2 # pointer to base of stack .lcomm debugptr,2 # pointer to debugging info .lcomm oldstack,4 # old stack from caller /* *==================================================================== */ .end
-- Andreas Jaeger, Director Platform / openSUSE, aj@suse.de SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg) Maxfeldstr. 5, 90409 Nürnberg, Germany GPG fingerprint = 93A3 365E CE47 B889 DF7F FED1 389A 563C C272 A126
Attachment:
pgp00000.pgp
Description: PGP signature
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |