flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > MZ/PE EXE - run Windows program on Android in DOSBox

Author
Thread Post new topic Reply to topic
alixgrin



Joined: 20 Mar 2025
Posts: 3
alixgrin 20 Mar 2025, 16:28
You ask why, if somebody already can Dalvik.
1. This allows to link with x86 code, JIT, etc.
2. We're safe if Google changes spec
3. Privacy - DOS apps don't show in Android package list
So, here's a little bit rough code... (run "cwsdpmi -p" first)
Upd: mouse.
Code:
format MZ
heap 0
segment loader use16
RVA equ (-65536)+
push cs
pop ds
mov ax,1687h
int 2Fh
jmp after_pe
times 12-$ db 0
mode_switch dd 0e0h
error:
mov ax,4CFFh
int 21h
after_pe:
or ax,ax
jnz error
test bl,1
jz error
mov word [mode_switch],di
mov word [mode_switch+2],es
mov bx,si
mov ah,48h
int 21h
jc error
mov dword[hdr_end-16],main
mov es,ax
mov ax,1
call far [mode_switch]
jc error
mov cx,1
xor ax,ax
int 31h
mov si,ax
xor ax,ax
int 31h
mov di,ax
mov dx,cs
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,si
mov ax,9
int 31h
mov dx,ds
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,di
int 31h
mov ecx,main-4352
shl ecx,4
mov dx,cx
shr ecx,16
mov ax,7
int 31h
mov bx,si
int 31h
mov cx,0FFFFh
mov dx,0FFFFh
mov ax,8
int 31h
mov bx,di
int 31h
mov ds,di
mov es,di
mov fs,di
mov gs,di
push 0
push si
push dword msdos_start
retfd
times 0e0h-$-48 db 0
db 'PE',0,0,76,1,1,0,0,0,0,0,0,0,0,0
db 0,0,0,0,224,0,15,1,11,1,1,73,0,0,0,0
db 0,0,0,0,0,0,0,0
dd RVA windows_start
db 0,0,0,0
db 0,0,0,0,0,0,1,0,0,16,0,0,0,2,0,0
db 1,0,0,0,0,0,0,0,3,0,10,0,0,0,0,0
db 0,0,1,0,0,2,0,0,0,0,0,0,2,0,0,0
db 0,16,0,0,0,16,0,0,0,0,1,0,0,0,0,0
db 0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0
db 0,16,0,0,0,240,0,0
times 7*16 db 0
db 46,116,101,120,116,0,0,0
db 0,240,0,0,0,16,0,0
dd code_end-code_start
db 0,2,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224
times 512-$-48 db 0
hdr_end:
segment main use32
org 65536+4096
code_start:
;windows gibberish
macro library [name,string] {
   forward
        dd 0,0,0,RVA name#.label,RVA name#.address
   common
        dd 0,0,0,0,0
   forward
        name#.label db string,0
        rb (RVA $) and 1
}
macro import name,[label,string] {
   common
        rb (- (RVA $)) and 3
        name#.address:
   forward
        local _label
        label dd RVA _label
   common
        dd 0
   forward
        _label dw 0
        db string,0
        rb (RVA $) and 1
}
  library kernel,'KERNEL32.DLL',\
          gdi,'GDI32.DLL',\
          user,'USER32.DLL'
  import kernel,\
    CreateThread,'CreateThread',\
    ExitProcess,'ExitProcess',\
    GetModuleHandleA,'GetModuleHandleA',\
    GetProcAddress,'GetProcAddress',\
    LoadLibraryA,'LoadLibraryA',\
    Sleep,'Sleep',\
    VirtualAlloc,'VirtualAlloc'
  import gdi,\
    CreateCompatibleDC,'CreateCompatibleDC',\
    CreateDIBSection,'CreateDIBSection',\
    SelectObject,'SelectObject',\
    SetDeviceGammaRamp,'SetDeviceGammaRamp',\
    SetStretchBltMode,'SetStretchBltMode',\
    StretchBlt,'StretchBlt'
  import user,\
    CreateWindowExA,'CreateWindowExA',\
    DefWindowProcA,'DefWindowProcA',\
    DispatchMessageA,'DispatchMessageA',\
    GetClientRect,'GetClientRect',\
    GetDC,'GetDC',\
    GetMessageA,'GetMessageA',\
    LoadCursorA,'LoadCursorA',\
    RegisterClassA,'RegisterClassA',\
    ReleaseDC,'ReleaseDC'
_SetProcessDPIAware db 'SetProcessDPIAware',0
rb ($$-$)and 3
bih dd 40,800,-600,200001h,0,0,0,0,0,0
wc dd 0,wndproc,0,0,0,0,0,0,0,app_name
;platform-independent
app_name db 'app',0
main_thread:
.again:
mov eax,0ff00ffh
mov edi,[surf]
mov ecx,800*600
rep stosd
call present
call [SwitchToThread]
jmp .again
ret
filtered:
dec [exitcnt]
jz exit
ret
exitcnt dd 3
;cross-platform
windows_present:
pusha
push [hwnd]
call [GetDC]
test eax,eax
jz .noop
mov ebx,eax
push 3
push ebx
call [SetStretchBltMode]
push 0cc0020h
push 600
push 800
push 0
push 0
push [memdc]
sub esp,16
mov eax,esp
push eax
push [hwnd]
call [GetClientRect]
push ebx
call [StretchBlt]
push ebx
push [hwnd]
call [ReleaseDC]
.noop:
popa
ret
present:
cmp dword[vesa_info.VESASignature],\
 41534556h
jnz exit
pusha
;mouse
xor ebx,ebx
mov eax,5
int 33h
test ebx,ebx
jz .notap
movzx ecx,cx
movzx edx,dx
call filtered
.notap:
mov eax,3
int 33h
movzx ecx,cx
movzx edx,dx
cmp ecx,800
jge .nocur
cmp edx,600
jge .nocur
imul edx,800
add edx,ecx
mov edi,[surf]
lea edi,[edi+edx*4]
mov eax,[mouserand]
mov edx,1
.again:
mov ecx,edx
push edi
rep stosd
pop edi
imul eax,1103515245
add eax,12345
add edi,800*4
inc edx
cmp edx,33
jnz .again
mov [mouserand],eax
.nocur:
;end mouse
mov esi,[surf]
mov edi,[mode_info.PhysBasePtr]
mov ecx,800*600*4
rep movsb
popa
ret
mouserand dd 0
windows_sleep:
 imul edx,55
 push edx
 call [Sleep]
 ret
sleep:
 mov ecx,[$$-12]
 add edx,[46ch+ecx]
.again:
 mov eax,1680h
 int 2fh
 mov eax,[46ch+ecx]
 cmp eax,edx
 jl .again
 ret
SwitchToThread dd 0
windows_switchtothread_slow:
 push 10
 call [Sleep]
 ret
msdos_switchtothread:
 mov eax,1680h
 int 2fh
 ret
windows_malloc:
 shl ebx,16
 push 64
 push 3000h
 push ebx
 push 0
 call [VirtualAlloc]
 test eax,eax
 jz exit
 mov ebx,eax
 ret
malloc:
 push ebx
 xor ecx,ecx
 mov eax,501h
 int 31h
 jc exit
 shl ebx,16
 mov bx,cx
 add ebx,[$$-12]
 xor eax,eax
 pop ecx
 shl ecx,16
 mov edi,ebx
 rep stosb
 ret
windows_exit:
 push 0
 call [ExitProcess]
exit:
 call ega
 mov eax,4c00h
 int 21h
;entry points
rainbow:
xor eax,eax
.again:
stosw
inc eax
cmp eax,256
jnz .again
ret
windows_start:
 mov word [present],0ebh+(windows_present-present-2)*256
 mov word [exit],0ebh+(windows_exit-exit-2)*256
 mov word [malloc],0ebh+(windows_malloc-malloc-2)*256
 mov word [sleep],0ebh+(windows_sleep-sleep-2)*256
 mov [SwitchToThread],windows_switchtothread_slow
 push user.label
 call [LoadLibraryA]
 test eax,eax
 jz exit
 push _SetProcessDPIAware
 push eax
 call [GetProcAddress]
 test eax,eax
 jz .w2k
 call eax
.w2k:
 xor esi,esi
 push esi
 call [GetDC]
 mov ebx,eax
 mov edi,vesa_info
 call rainbow
 call rainbow
 call rainbow
 push vesa_info
 push ebx
 call [SetDeviceGammaRamp]
 push ebx
 call [CreateCompatibleDC]
 mov ebx,eax
 mov [memdc],ebx
 push esi
 push esi
 push surf
 push esi
 push bih
 push ebx
 call [CreateDIBSection]
 test eax,eax
 jz exit
 push eax
 push ebx
 call [SelectObject]
 push esi
 call [GetModuleHandleA]
 mov ebx,eax
 push 32512
 push esi
 call [LoadCursorA]
 mov ecx,wc
 mov [ecx+16],ebx
 mov [ecx+24],eax
 push wc
 call [RegisterClassA]
 test eax,eax
 jz exit
 push esi
 push ebx
 push esi
 push esi
 push 600
 push 800
 push esi
 push esi
 push 11cf0000h
 mov ecx,app_name
 push ecx
 push ecx
 push esi
 call [CreateWindowExA]
 test eax,eax
 jz exit
 mov [hwnd],eax
 push tid
 push esi
 push esi
 push thread_entry
 push esi
 push esi
 call [CreateThread]
 sub esp,28
 mov ebp,esp
.ui_thread:
 push 0
 push 0
 push 0
 push ebp
 call [GetMessageA]
 test eax,eax
 jz exit
 cmp eax,-1
 jz exit
 push ebp
 call [DispatchMessageA]
 jmp .ui_thread
msdos_start:
 mov ecx,[$$-16]
 sub ecx,4352
 shl ecx,4
 neg ecx
 mov [$$-12],ecx
 mov [SwitchToThread],msdos_switchtothread
 call vesa
 mov ebx,31
 call malloc
 mov [surf],ebx
;mouse
 xor eax,eax
 int 33h
 xor ecx,ecx
 mov edx,800
 mov eax,7
 int 33h
 mov edx,600
 mov eax,8
 int 33h
 xor edx,edx
 mov eax,4
 int 33h
thread_entry:
 call main_thread
 jmp exit
;non-portable
wndproc:
mov eax,[esp+8]
cmp eax,514
jnz .nomouse
pusha
sub esp,16
mov eax,esp
push eax
push [hwnd]
call [GetClientRect]
mov esi,[esp+8]
mov edi,[esp+12]
movzx eax,word[esp+64]
imul eax,800
cdq
idiv esi
mov ecx,eax
movzx eax,word[esp+66]
imul eax,600
cdq
idiv edi
mov edx,eax
call filtered
add esp,16
popa
.nomouse:
cmp eax,2
jz exit
jmp [DefWindowProcA]
ega:
 cmp [already_ega],0
 jnz .done
 mov eax,3
 int 10h
 xor ebx,ebx
 mov eax,1112h
 int 10h
 mov [already_ega],1
.done:
 ret
already_ega db 0
vesa:
 mov eax,19
 int 10h
 mov [already_ega],0
 cmp dword[vesa_info.VESASignature],\
  41534556h
 jz .already
 mov [DpmiRegRec.lRegAX],4f00h
 mov [DpmiRegRec.lRegDI],vesa_info-$$
 mov ebx,[$$-16]
 mov [DpmiRegRec.wRegES],bx
 mov ebx,10h
 call dpmi_int
 test byte[DpmiRegRec.lRegAX+1],255
 jnz exit
 cmp dword[vesa_info.VESASignature],\
  41534556h
 jnz exit
 cmp byte[vesa_info.VESAVersion+1],2
 jb exit
 mov esi,[vesa_info.VideoModePtr]
 mov edx,esi
 shr edx,16
 shl edx,4
 add edx,[$$-12]
 movzx esi,si
 add esi,edx
 xor eax,eax
.modes:
 lodsw
 cmp ax,-1
 jz exit
 mov [DpmiRegRec.lRegAX],4f01h
 mov [DpmiRegRec.lRegDI],mode_info-$$
 mov ebx,[$$-16]
 mov [DpmiRegRec.wRegES],bx
 mov [DpmiRegRec.lRegCX],eax
 mov ebx,10h
 call dpmi_int
 test byte[DpmiRegRec.lRegAX+1],255
 jnz exit
 mov al,byte[mode_info.ModeAttributes]
 and eax,25+128
 cmp eax,25+128
 jnz .modes
 cmp [mode_info.XResolution],800
 jnz .modes
 cmp [mode_info.YResolution],600
 jnz .modes
 cmp [mode_info.NumberOfPlanes],1
 jnz .modes
 cmp [mode_info.MemoryModel],6
 jnz .modes
 cmp [mode_info.BitsPerPixel],32
 jnz .modes
 cmp [mode_info.RedMaskSize],8
 jnz .modes
 cmp [mode_info.GreenMaskSize],8
 jnz .modes
 cmp [mode_info.BlueMaskSize],8
 jnz .modes
 cmp [mode_info.GreenMaskPos],8
 jnz .modes
 mov ebx,[esi-2]
 or bh,40h
 mov [vesa_mode],bx
 mov ecx,[mode_info.PhysBasePtr]
 mov ebx,[mode_info.PhysBasePtr+2]
 mov esi,30
 xor edi,edi
 mov eax,800h
 stc
 int 31h
 jc exit
 shl ebx,16
 mov bx,cx
 add ebx,[$$-12]
 mov [mode_info.PhysBasePtr],ebx
.already:
 mov eax,4f02h
 movzx ebx,[vesa_mode]
 int 10h
 ret
dpmi_int:
 mov [DpmiRegRec.lRes],0
 mov [DpmiRegRec.wRegSP],0
 mov [DpmiRegRec.wRegSS],0
 mov edi,DpmiRegRec
 xor ecx,ecx
 mov eax,300h
 stc
 int 31h
 jc exit
 ret
surf rd 1
vesa_info:
.VESASignature db 'VBE2'
virtual at $
.VESAVersion rw 1
.OEMStringPtr rd 1
.Capabilities rb 4
.VideoModePtr rd 1
.TotalMemory rw 1
.OemSoftwareRev rw 1
.OemVendorNamePtr rd 1
.OemProductNamePtr rd 1
.OemProductRevPtr rd 1
.Reserved rb 222
.OemData rb 256
DpmiRegRec:
.lRegDI rd 1
.lRegSI rd 1
.lRegBP rd 1
.lRes rd 1
.lRegBX rd 1
.lRegDX rd 1
.lRegCX rd 1
.lRegAX rd 1
.wFlags rw 1
.wRegES rw 1
.wRegDS rw 1
.wRegFS rw 1
.wRegGS rw 1
.wRegIP rw 1
.wRegCS rw 1
.wRegSP rw 1
.wRegSS rw 1
end virtual
virtual at vesa_info;windows only
memdc rd 1
hwnd rd 1
tid rd 1
end virtual
virtual at vesa_info.VESAVersion
vesa_mode rw 1
mode_info:
.ModeAttributes rw 1
.WinAAttributes rb 1
.WinBAttributes rb 1
.WinGranularity rw 1
.WinSize rw 1
.WinASegment rw 1
.WinBSegment rw 1
.WinFuncPtr rd 1
.BytesPerScanLine rw 1
.XResolution rw 1
.YResolution rw 1
.XCharSize rb 1
.YCharSize rb 1
.NumberOfPlanes rb 1
.BitsPerPixel rb 1
.NumberOfBanks rb 1
.MemoryModel rb 1
.BankSize rb 1
.NumberOfImagePages rb 1
.Reserved_page rb 1
.RedMaskSize rb 1
.RedMaskPos rb 1
.GreenMaskSize rb 1
.GreenMaskPos rb 1
.BlueMaskSize rb 1
.BlueMaskPos rb 1
.ReservedMaskSize rb 1
.ReservedMaskPos rb 1
.DirectColorModeInfo rb 1
.PhysBasePtr rd 1
.OffScreenMemOffset rd 1
.OffScreenMemSize rw 1
.LinBytesPerScanLine rw 1
.BnkNumberOfPages rb 1
.LinNumberOfPages rb 1
.LinRedMaskSize rb 1
.LinRedFieldPos rb 1
.LinGreenMaskSize rb 1
.LinGreenFieldPos rb 1
.LinBlueMaskSize rb 1
.LinBlueFieldPos rb 1
.LinRsvdMaskSize rb 1
.LinRsvdFieldPos rb 1
.MaxPixelClock rd 1
.Reserved rb 190
end virtual
times ($$-$)and 511 db 0
code_end:
    
[/code]
Post 20 Mar 2025, 16:28
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.