1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
|
#!/usr/bin/env python
#
# __COPYRIGHT__
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
import sys
import time
import TestSCons
test = TestSCons.TestSCons()
if sys.platform != 'win32':
test.skip_test('PharLap is only available on Windows; skipping test.\n')
if not test.detect_tool('linkloc'):
test.skip_test("Could not find 'linkloc', skipping test.\n")
if not test.detect_tool('386asm'):
test.skip_test("Could not find '386asm', skipping test.\n")
# From the Phar Lap minasm example program...
test.write("minasm.asm", r"""
;
; MINASM.ASM - A minimal assembly language program which runs
; under ToolSuite. You can use this program as a framework
; for large assembly language programs.
;
.386
;
; Segmentation and segment ordering.
;
; First comes the code segment.
;
_TEXT segment use32 byte public 'CODE'
_TEXT ends
;
; The data segment contains initialized RAM based data. It will automatically
; be placed in the ROM at link time and unpacked into RAM at run-time
; by the __pl_unpackrom function.
;
; If you do not need any initialized data in your assembly language program,
; you can leave this segment empty and remove the call to __pl_unpackrom.
;
;
_DATA segment use32 dword public 'DATA'
loopcount dd 10d
rammessage db 'This message is in RAM memory',0dh,0ah,0
_DATA ends
;
; The BSS segment contains RAM based variables which
; are initialized to zero at run-time. Putting unitialized
; variables which should start at zero here saves space in
; the ROM.
;
; If you do not need any zero-initialized data in your assembly language
; program, you can leave this segment empty (and optionally remove the
; instructions below which initialize it).
;
; The segment name must be lower case for compatibility with the linker
;
_bss segment use32 dword public 'BSS'
dummy_bss db 32 dup(?) ; Use a little bit of BSS just to test it
_bss ends
;
; The const segment contains constants which will never
; change. It is put in the ROM and never copied to RAM.
;
; If you do not need any ROM based constants in your assembly language
; program, you can leave this segment empty.
;
_CONST segment use32 dword public 'CONST'
rommessage db 'This message is in ROM memory',0dh,0ah,0
_CONST ends
;
; We're in flat model, so we'll put all the read-only segments we know about
; in a code group, and the writeable segments in a data group, so that
; we can use assume to easily get addressability to the segments.
;
CGROUP group _TEXT, _CONST
DGROUP group _DATA, _bss
assume cs:CGROUP,ds:DGROUP
_TEXT segment
;
; _main - the main routine of this program.
;
; We will display the RAM and ROM messages the number of times
; specified in the loopcount variable. This proves that we can
; initialize RAM data out of ROM and the fact that we can
; modify the loop count in memory verifies that it actually ends
; up in RAM.
;
public _main
_main proc near
mov cl,0ah ; Skip a line before we start
call PutCharTarget ;
main_loop:
cmp loopcount,0 ; Are we at the end of our loop?
je short done_main ; yes.
lea edx,rommessage ; EDX -> ROM message
call WriteStringTarget ; Display it
lea edx,rammessage ; EDX -> RAM message
call WriteStringTarget ; Display it
dec loopcount ;
jmp main_loop ; Branch back for next loop iteration
done_main:
ret ; That's it!
_main endp
;
; WriteStringTarget - Display a string on the target console
;
; Inputs:
; EDX -> Null terminated ASCII string to display
;
; Outputs:
; All registers preserved
;
WriteStringTarget proc near
push ecx ; Save registers
push edx ;
write_loop:
movzx ecx,byte ptr [edx] ; Get a character
jecxz done_str ; Branch if end of string
call PutCharTarget ; Display this character
inc edx ; Bump scan pointer
jmp write_loop ; And loop back for next character
done_str:
pop edx ; Restore registers
pop ecx ;
ret ; and return
WriteStringTarget endp
;
; PutCharTarget - Write a character on the target console
;
; This routine displays a character on the target console by using
; the PutChar kernel service available through int 254.
;
; Inputs:
; CL = character to display
;
; Outputs:
; All registers preserved
;
PutCharTarget proc near
push eax ; Save registers
push ebx ;
push edx ;
mov ax,254Ah ; Request Kernel Service
mov bx,1 ; service code 1 = PutChar
movzx edx,cl ; EDX = character to display
int 0FEh ; Int 254 is for kernel services
pop edx ; Restore registers
pop ebx ;
pop eax ;
ret ; and return
PutCharTarget endp
;
; The __pl_unpackrom unpacks initialized RAM based data variables
; out of the ROMINIT segment into their RAM area. They are put
; in the ROMINIT segment with the -ROMINIT switch in the link file.
;
extrn __pl_unpackrom:near
;
; The _EtsExitProcess function is used to terminate our program
;
extrn _EtsExitProcess:near
;
; The linker will define symbols for the beginning and end of the
; BSS segment.
;
extrn __p_SEG__bss_BEGIN:dword
extrn __p_SEG__bss_END:dword
;
; __p_start -- The entry point for our assembly language program.
; We unpack the RAM based variables out of the ROM and clear the
; BSS to zero, then call _main where the real work happens. When
; _main returns, we call EtsExitProcess(0) to terminate.
;
public __p_start
__p_start proc near
pushad ; save initial regs
push es ;
call __pl_unpackrom ; Call the unpacker
cld ; Clear direction flag
lea eax,__p_SEG__bss_END ; load end address and
lea ebx,__p_SEG__bss_BEGIN ; subtract start to get size
sub eax,ebx
mov ecx,eax ; This is size
inc ecx
lea edi,__p_SEG__bss_BEGIN ; Zero from start address
mov al,0 ;Zero out BSS and C_COMMON
rep stosb
pop es ; restore initial regs
popad
call _main ; go do some work
stopme:
xor eax,eax ; Call _EtsExitProcess(0)
push eax ;
call _EtsExitProcess ;
pop eax ;
jmp stopme ; .. in a loop just in case it ever
; comes back
__p_start endp
TD_hack:
mov eax, __p_tdhack ; force reference to TD-hack symbol
_TEXT ends
;
; Hack for Turbo Debugger/TDEMB - TD will fault if the .exe being
; debugged doesn't have an import table. (TD looks for the address of
; the table, then dereferences that address wihtout checking for NULL).
;
; This symbol, __p_tdhack, must be declared as an import in all the
; .emb files shipped. IE:
;
; -implib embkern.lib
; -import __p_tdhack
;
; This forces the creation of an import table within the .EXE.
_DATA segment
extrn __p_tdhack:dword
_DATA ends
end __p_start
""")
test.write("foo.lnk","""
@baz\\bar.lnk
""")
test.subdir("baz")
test.write([ "baz", "bar.lnk"],"""
@asm.emb
""")
test.write("SConstruct", """
env=Environment(tools = [ 'linkloc', '386asm' ],
ASFLAGS='-twocase -cvsym',
LINKFLAGS='@foo.lnk')
env.Program(target='minasm', source='minasm.asm')
""")
test.run(arguments='.')
# Assume .exe extension...this test is for Windows only.
test.fail_test(not os.path.exists('minasm.exe'))
test.up_to_date(arguments='.')
# Updating a linker command file should cause a rebuild!
test.write([ "baz", "bar.lnk"],"""
-cvsym
@asm.emb
""")
oldtime = os.path.getmtime(test.workpath('minasm.exe'))
time.sleep(2) # Give the time stamp time to change
test.run(arguments = '.')
test.fail_test(oldtime == os.path.getmtime(test.workpath('minasm.exe')))
test.pass_test()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:
|