The MASM Forum Archive 2004 to 2012

Miscellaneous Forums => 16 bit DOS Programming => Topic started by: Prince Wotoshi on November 01, 2008, 08:09:19 PM

Title: Smallest Executable to write "Hello World" to the screen
Post by: Prince Wotoshi on November 01, 2008, 08:09:19 PM
With a couple of guys we have a challenge who can write the smallest executable being able to print "Hello World".
Since the .com files would be the smallest possible, this is the current target.

Using a little trick (command line argument) I'm up to 7 bytes:


mov ah,09h
mov dx,82h
int 21h

which can be run: test.com Hello World$
and it would print Hello World to the screen.

The only way I could come up with to make it another byte shorter is:


mov ah,09h
mov dl,82h
int 21h

This should work the same, but gives an error instead:
Quote
Administrator: cmd.exe - test3.com hello$
The NTVDM CPU has encountered an illegal instruction.
CS:11ed IP:0024 OP:ff ff ff ff ff Choose 'Close' to terminate the application.

I know I'm assuming an empty DH here, but when I run both versions through debug.exe the registers are identical (except for the IP which is off by one byte of course).
Shouldn't this just work or am I missing something here?

Any other ideas to make it even shorter?

Thanks!
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: sinsi on November 01, 2008, 10:35:07 PM

.model tiny
.286
.code
org 100h
go: mov al,dh
    call phex8
    ret
phex8:  ror al,4
        call phex4
        ror al,4
phex4:  push ax
        and al,15
        cmp al,10
        sbb al,105
        das
        mov dl,al
        mov ah,2
        int 21h
        pop ax
        ret

end go

This code gives me "05" as the result, so I guess DH isn't 0 after all...
You should really have a "ret" at the end of your code too.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Prince Wotoshi on November 01, 2008, 11:20:26 PM
strange, it gives 11 for me when I run your code, but when I run it through debug.exe:


AX=0000  BX=0000  CX=001F  DX=0000  SP=FFFE  BP=0000  SI=0000  DI=0000
DS=17AB  ES=17AB  SS=17AB  CS=17AB  IP=0102   NV UP EI PL NZ NA PO NC
17AB:0102 E80100        CALL    0106

Both AX and DX are 0 after the first line of code....
So debug.exe doesn't work like it should then?

I know about the ret that should be there, but it doesn't help in size :D

Thanks for your reply!
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: sinsi on November 02, 2008, 12:27:02 AM
The only registers initialised by DOS for a .com program are AL,AH,DS,ES,SS and SP, all others are 'undefined' - they could be anything, usually what DOS left in there.
Debug initialises BX:CX to the program's size, maybe it zeroes out other registers? For me, debugging any program shows DX=0.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: MichaelW on November 02, 2008, 03:42:19 AM
Debug zeros AX, DX, BP, SI, and DI by design.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Prince Wotoshi on November 02, 2008, 10:06:39 AM
Ahhh, so that explains why it looks ok.
Well, then 7 bytes really is the smallest we can go, I think.

Thanks for your answers!
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: FORTRANS on November 02, 2008, 01:32:07 PM
Hi,

   Yes I just got bitten by the difference between DEBUG and
normal loading of a program.  Look at the GENERAL.TXT file
in the Hugi Compo rules for a good description of the start up
register contents.

http://www.hugi.scene.org/compo/

   The DI register was zeroed by DEBUG, which "fixed" an error
in my code.

Cheers,

Steve N.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: jj2007 on November 02, 2008, 04:55:33 PM
Quote from: Prince Wotoshi on November 01, 2008, 08:09:19 PM
Using a little trick (command line argument) I'm up to 7 bytes:


mov ah,09h
mov dx,82h
int 21h

which can be run: test.com Hello World$
and it would print Hello World to the screen.

Without the ret, I get a lot of garbage until it prints Hello. Are the rules of your game unspecific enough to tolerate the garbage?
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Prince Wotoshi on November 02, 2008, 08:49:47 PM
Are you sure you have the $ at the end of the argument?
It works perfectly for me on vista. This the file (program) if you look at it from a hex editor:


B409 BA8200 CD21


And no it's not allowed to see garbage ;), but for me it doesnt......
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: zemtex on October 05, 2010, 07:52:00 AM
Hey Prince Wotoshi. I see that you have a captains of crush gripper in your avatar. It was funny to see that there are grip trainers in this forum. I have closed the CoC 3.5 myself from a choked position and I have repped the CoC 3 from a non-choked position for about 6 reps.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Prince Wotoshi on October 05, 2010, 12:51:43 PM
Yes, I did a lot of grip training in the past :)
repping the #3 is a nice achievement, as well as closing the #3.5 from a choke. Good job!
I did both as well, but was not able to become COC certified. My small hands really gave me the disadvantage on the credit card set.
I got Mash monster certified with my #3 though, and the pic you see in my avatar is the #3.

I'm also red nail certified, but achieving that was a lot easier :)

But like I said, I did a lot in the past. Now I sometimes still do it, but I cannot close the #3 consistently anymore. Only on good days ;)

Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: zemtex on October 05, 2010, 07:23:17 PM
I have nails here myself. I havent trained much with them because I tend to run out of nails pretty quickly, and it takes a while to order new ones. I'm not in america. I bend blue nails very easily, but the red nail is not in reach yet.

I train with alot of equipment related to grip and forearm development. Here is a list of equipment/exercises I use frequently:

1: Captains of Crush grippers (I have dual sets of all of them)
2: Heavy Grips grippers (I have all of them)
3: Ironmind Wrist Roller (This one is really effective, it gives you a forearm pump like nothing else i've tried)
4: Ironmind pinch grip block (This one gets on the pinch grip)
5: Ironmind Rolling Thunder (I like this one)
6: Hammer Bar (I ordered this from an armwrestling store, its an effective tool, you mount weight plates onto it)
7: Hercules Bar (This is also a good forearm developer)
8: I use normal weight plates in my hand and curl them with my wrist, I can almost handle 15 kg plates now)

My bench press is really bad at the moment, but my deadlift is 280 kg and my squat is 210 kg. Overhead press is 100 kg x 3 reps so far.
Bicep curl is 90 kg x 3 reps at most.

My strongest area is definitely deadlift. I am trying to improve my bench, I can barely handle 120 kg in the bench. I have very long arms, it could be because of that i'm not sure.

Anyways, good day!

BTW: I understand the emotional situation one can get into after years of training. You get tired, cant afford enough protein, motivation is lost etc. It takes effort to get back into a good pattern again. I struggle with this myself.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: xandaz on October 05, 2010, 10:59:36 PM
you must keep in mind that interrupts are executable code.
this i think may be smaller. works only for text mode.

      mov ax,0b800h
      mov es,eax
      lea esi,HelloString
      mov edi,0
      mov cx,sizeof HelloString
loop:
      lodsb
      mov ah,07h ; not sure if attr should be ah or al long time no DOS
      stosw
      dec cx
      jcxz end_loop
      jmp loop
end_loop:
      int 20h
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: xandaz on October 05, 2010, 11:14:16 PM
   Not sure how this stiff works anymore . It gives invalid fixup .

.286
.model tiny

.data

HelloString     db      'Hello World'

.code
org     100h
        _start:
               mov     ax,0b800h
               mov     es,ax
               lea       si,HelloString
               mov     di,0
               mov     cx,sizeof HelloString
               cld

string_loop:
               lodsb
               mov     ah,7
               stosw
               dec cx
               jcxz  end_loop
               jmp   string_loop
end_loop:
               int      20h
               
end     _start
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: redskull on October 06, 2010, 01:04:02 AM
37 bytes, 15 of code?

.286
.model tiny
option casemap:none

.data
out_string  db "H", 07h, "e",07h, "l", 07h,"l", 07h,"o", 07h," ", 07h,"W", 07h,"o", 07h,"r", 07h,"l", 07h,"d", 07h

.code
org 0100h
start:   
   
    mov dx,0b800h
    mov es,dx
    mov cl, SIZEOF out_string
    mov si, OFFSET out_string
move:
    lodsw
    stosw
    loop move
    ret

end start
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: dedndave on October 08, 2010, 01:16:20 AM
i think you need the 8th byte...
mov ah,9
mov dx,82h
int 21h
ret

as for relying on DH=0, not sure that is a valid assumption under NTVDM
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: xandaz on November 19, 2010, 02:59:26 PM
   yeah,... well lets not forget that int 21h is a far call. So there's code beneath the instruction... Is it smaller? Don't know....
    bye
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: dedndave on November 19, 2010, 03:52:12 PM
that is true however, .COM programs are executed similar to a NEAR CALL
the reason a RETN instruction exits is that an INT 20h instruction is at CS:0000 and a 0000 pushed on the stack at program entry
(CS = PSP)
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: xandaz on November 20, 2010, 12:44:58 AM
   ok ... i'm not sure we're understanding each other. If i do this...

call PrintHelloWorldAndExit

...is everyone going to disregard the code parts in this procedure call?
   No? Yay, ive won!!!
   LMAO :)
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 12:48:31 AM
Did you talk about 16 programs only, or for Win32, too?
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: xandaz on November 20, 2010, 12:51:02 AM
   i think its DOS only antariy
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 12:53:52 AM
Quote from: xandaz on November 20, 2010, 12:51:02 AM
   i think its DOS only antariy

Well, if it been Win32, then I can suggest a candidate...
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: jj2007 on November 20, 2010, 12:55:31 AM
It's .com, actually... and it's 8 bytes short:
.model tiny

.code
org 100h
start:
mov ah, 09h ; write string to STDOUT
mov dx, 82h ; get command line
int 21h ; show it... ;-)
ret
end start


If that looks too complex, try this:
.model tiny
.code
dq 0C321CD0082BA09B4h
end


Batch file for testing:
Quote@ECHO OFF
HelloWorldDOS.com Hellooo... world of Masm!$
echo.
echo.
echo.
echo.
pause

Quote from: Antariy on November 20, 2010, 12:53:52 AM
Well, if it been Win32, then I can suggest a candidate...

Which one?
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 01:12:12 AM
Quote from: jj2007 on November 20, 2010, 12:55:31 AM
Quote from: Antariy on November 20, 2010, 12:53:52 AM
Well, if it been Win32, then I can suggest a candidate...

Which one?

You are know   :lol
But it not only print HelloWorld  :wink
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 01:17:55 AM
Quote from: jj2007 on November 20, 2010, 12:55:31 AM
It's .com, actually... and it's 8 bytes short:

I can suggest to put code into command line specification, and at start of the program put the 2 byte jump to the command line  :wink

So, you just needed to avoid binary null in the code (this is easy), and enter the code as command line for the 2 bytes program, which just jump to command line.

But I must warn that under Windows this is a bit tricky due to encodings difference. So, this is reliablest from DOS.

Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 01:24:00 AM
Command line is something like (in hex, convert it to dec and enter it with Alt codes):

B4 09 31 D2 B2 8B CD 21 C3 48 65 6C 6C 6F 2C 57 6F 72 6C 64 24


The program is:

jmp 82

Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: jj2007 on November 20, 2010, 01:30:46 AM
jmp 82h but...:
error A2076: jump destination must specify a label
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 01:35:34 AM
There is a test with 2 byte program which print HelloWorld.
To simplify things with different encodings, is written an .BAT file.
On my system it works.


Alex
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: jj2007 on November 20, 2010, 01:45:18 AM
Thanks, Alex - works like a charm on Win XP SP2...

.model tiny
.code
dw 080EBh
end

Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 01:46:52 AM
Update in .BAT file - pause>nul
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: oex on November 20, 2010, 01:47:10 AM
It actually prints "Hello,World" for me, not space but comma, is that legal? :lol

(I tried it with space and that worked also :lol)

PS. Does that mean I technically win :lol
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 01:49:24 AM
Quote from: oex on November 20, 2010, 01:47:10 AM
It actually prints "Hello,World" for me, not space but comma, is that legal? :lol

(I tried it with space and that worked also :lol)

This is correct - I used not space.

For pure historical DOS, there is one more update  :lol



Alex
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: jj2007 on November 20, 2010, 01:55:52 AM
Any idea why jmp word ptr ss:[82h] does not work?
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 01:57:51 AM
Quote from: jj2007 on November 20, 2010, 01:55:52 AM
Any idea why jmp word ptr ss:[82h] does not work?

Because this is level of inderection - you jump not to address 82, but to address, which is specified in WORD placed at address 82.
I guess my English not help...
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 02:02:11 AM
Quote from: oex on November 20, 2010, 01:47:10 AM
It actually prints "Hello,World" for me, not space but comma, is that legal? :lol

By the way, you can enter very very very long (up to ~110 chars) string for printing - and this will have no influence for program size  :bg

P.S. you can edit .BAT file because it contain only printable chars.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: GregL on November 20, 2010, 02:16:00 AM
Alex,

Your program + .bat file works on Vista (32-bit) too.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 02:18:35 AM
Quote from: GregL on November 20, 2010, 02:16:00 AM
Alex,

Your program + .bat file works on Vista (32-bit) too.

Thank you, Greg!
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: japheth on November 20, 2010, 07:53:22 AM
This "EB 80" 2-byte program was also discussed in the FASM forum:

http://board.flatassembler.net/topic.php?t=10847

here's the clean Masm version, without tricks like "JMP $-7Eh":


CGROUP group PSP, _TEXT

PSP segment at 0
db 82h dup (?)
cmdl:
db 7eh dup (?)
PSP ends

_TEXT segment 'CODE'
start:
jmp short cmdl
_TEXT ends

end start


to be linked with "link16 /tiny ..."
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: dedndave on November 20, 2010, 11:32:55 AM
there is nothing wrong with this method, either...
        .MODEL  TINY

_TEXT   SEGMENT WORD PUBLIC 'CODE'

        ORG     82h
Branch:

        ORG     100h
_main   PROC    NEAR

        jmp     Branch

_main   ENDP

_TEXT   ENDS

        END     _main

of course, you can use a Start: label instead of a _main proc, if you prefer

thing is - if you need a batch file to get the results, i say you have defeated the purpose of the contest   :P
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: jj2007 on November 20, 2010, 11:58:47 AM
Quote from: dedndave on November 20, 2010, 11:32:55 AM
thing is - if you need a batch file to get the results, i say you have defeated the purpose of the contest   :P

You don't need a batch file, actually. But you should know how to use Alt nnn at the DOS prompt :bg
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: dedndave on November 20, 2010, 12:06:44 PM
i know how to do it   :P
but, who can remember the sequences   :lol
it reminds me of booting a tape drive on a PDP11 with the front panel switches
a sequence which i, at one time, had memorized - now happily forgotten

at any rate, the point of the post: you don't need to open a segment at 0 for the PSP
the code segment naturally encompasses the PSP in a .COM program
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: japheth on November 20, 2010, 04:25:51 PM
Quote from: dedndave on November 20, 2010, 12:06:44 PM
at any rate, the point of the post: you don't need to open a segment at 0 for the PSP
the code segment naturally encompasses the PSP in a .COM program

You're right. I had the idea that with the AT segment there is no risk that a linker adds 256 null- bytes to "fill" the gap, but this isn't necessary. Also, some linkers won't accept an AT segment in a group.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 09:18:37 PM
Quote from: dedndave on November 20, 2010, 11:32:55 AM
thing is - if you need a batch file to get the results, i say you have defeated the purpose of the contest   :P

Well, since I saw that other programs  uses passed string as Message, that why I cannot use passed string for code?
The program itself is just vulnerable application, which allow execution of arbitrary code, code in shell-style. :P

So, my version is just from model line of: "http://www.masm32.com/board/index.php?topic=10252.msg125593#msg125593"  :wink



Alex
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 20, 2010, 09:31:00 PM
Quote from: japheth on November 20, 2010, 07:53:22 AM
This "EB 80" 2-byte program was also discussed in the FASM forum:

I'm have nothing to say contrary. For 30 years of DOS existence, I'm sure - thousands of peoples reinvent the same many times.



Alex
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: japheth on November 21, 2010, 09:07:16 AM
Quote from: Antariy on November 20, 2010, 09:31:00 PM
I'm have nothing to say contrary. For 30 years of DOS existence, I'm sure - thousands of peoples reinvent the same many times.
My post was merely informational.
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: Antariy on November 21, 2010, 10:38:09 AM
Quote from: japheth on November 21, 2010, 09:07:16 AM
My post was merely informational.

No problem, I'm understand that  :U



Alex
Title: Re: Smallest Executable to write "Hello World" to the screen
Post by: dedndave on November 21, 2010, 11:44:09 AM
QuoteYou're right. I had the idea that with the AT segment there is no risk that a linker adds 256 null- bytes to "fill" the gap, but this isn't necessary. Also, some linkers won't accept an AT segment in a group.

yes - that may happen if you stuck anything more than a label there
over the years, using different versions of different assemblers...
you can sometimes get away with DW ? - sometimes not
ORG xx LABEL DWORD or ORG xx BranchLabel: always seem to work

the only time i have used SEGMENT AT is when i wanted to access the interrupt vector table (even then it isn't needed)
or when writing ROMable code
it matters if you want to generate proper segment values in far addresses

as i said, it isn't needed when accessing the IVT, because i generally do not access that memory in 0000:0000 context
rather, i use something like XOR AX,AX - MOV DS,AX - then access the vector offsets