Out of curiosity, I wanted to see if it was possible to have one binary file running on two different architectures - without modifications.
My target platforms were 32-bit x86 Win/DOS and, big surprise here, the C64. If only I could craft a header that the x86 would chomp through, I could sneak in a small JMP there to either x86 or 6510 code somehow.
The first thing I did was to create a minimal file on the C64, containing only the BASIC header which calls a machine code subroutine in the loaded program. The experienced user will recognize the program "0 SYS2062" in here:
00 0C 08 00 00 9E 32 30 36 32 00 00 00 00
Disassembling this on a PC yields the following result:
1858:0100 0008 ADD [BX+SI],CL 1858:0102 000C ADD [SI],CL 1858:0104 0800 OR [BX+SI],AL 1858:0106 009E3230 ADD [BP+3032],BL 1858:010A 36 SS: 1858:010B 3200 XOR AL,[BX+SI] 1858:010D 0000 ADD [BX+SI],AL
This is looking good, this could actually work! The only thing worrying me is the SS:, but I can replace that with another instruction by modifying the SYS address. By changing the address to 2200, the disassembly looks like this:
1858:0100 0008 ADD [BX+SI],CL 1858:0102 000C ADD [SI],CL 1858:0104 0800 OR [BX+SI],AL 1858:0106 009E3232 ADD [BP+3232],BL 1858:010A 3030 XOR [BX+SI],DH 1858:010C 0000 ADD [BX+SI],AL 1858:010E 0000 ADD [BX+SI],AL
Exquisite! These instructions will not cause any problems for the code I'm about to append. So, the next step I did was to create a new file, simply printing "Hello world" out in DOS. I did this in DEBUG.EXE, in the lack of an x86 assembler.
1858:0100 B409 MOV AH,09h 1858:0102 BA0901 MOV DX,0109h 1858:0105 CD21 INT 21h 1858:0107 CD20 INT 20h
What follows at address $0109 is the text to be printed.
Next step was to merge the C64 header with the x86 code above, and at the same time include a test program for the 6510 processor. This time, I'm using the ACME assembler:
!CPU 6510 *=$800 !byte $00,$0c,$08,$00,$00,$9e,$32 !byte $32,$30,$30,$00,$00,$00,$00 *=$80e ; x86 code !byte $90,$90,$90 ; NOP NOP NOP !byte $b4,$09 ; MOV AH,9h !byte $ba,$1c,$01 ; MOV DX,011Ch !byte $cd,$21 ; INT 21h !byte $cd,$20 ; INT 20h !text "This program requires a Commodore 64.$" *=$898 ; 2200 lda #0 sta $d020 ; set border color black rts
Does it run in DOS? Let's see:
...and does it run on a C64? Does it? Does it?
IT DOES! Success! Now, off to write the first 32-bit x86 / C64 virus ever made, and conquer the world!