News for hackers. Stuff that matters.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by colejohnson66 on Sunday October 30, 2022 @04:35PM (#33398380)
Impressive! Is there a reason to jump over the string instead of just having the string after the program? Seems like one could save two bytes doing that.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by Agingcoder on Sunday October 30, 2022 @04:38PM (#33398414)
The COM executable gets loaded by DOS at address 100h, so the first bytes have to be executable code, if memory serves me well?
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by vore on Sunday October 30, 2022 @04:45PM (#33398472)
I think OP is saying what if you wrote it as:

        mov ah, 9
        mov dx, offset helloworld
        int 21
        mov ah, 0
        int 21
    .helloworld:
        db 'hello, world', d, A, '$'
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by dmitrygr on Sunday October 30, 2022 @04:44PM (#33398465)
You are right and sister comment to this one is wrong. Thusly:

MOV AH, 9

MOV DX, str

INT 21

MOV AH, 0

INT 21

Str:

DB 'hello, world', d, A, '$'

Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by q-big on Sunday October 30, 2022 @05:09PM (#33398738)
This program can be simplified further:

  MOV AH, 9
  MOV DX, str
  INT 21
  RET
  str:
  DB 'hello, world', d, A, '$'
Why can

  MOV AH, 0
  INT 21
be replaced by RET? Here is the answer: https://stackoverflow.com/a/60805758

UPDATE: Under https://news.ycombinator.com/item?id=33398592 userbinator posted an additional possible optimization.

Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by ralferoo on Sunday October 30, 2022 @06:11PM (#33399395)
Not a size optimisation, but a performance optimisation...

  INT 21
  RET
can be replaced with

  JP 5
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by blueflow on Sunday October 30, 2022 @07:02PM (#33399952)
That mnemonic would be "JMP" on x86. At address 5 in the PSP is the CP/M-style syscall entry point, it is not advised to not use it because it relies on the A20 line being short-circuited to zero, which cannot be relied on in later MS-DOS versions.

I don't see why this would be faster than using RET directly and having the INT 20 opcode at address 0 do the work.

Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by jart on Monday October 31, 2022 @01:33AM (#33402389)
Jump parity? But according to http://www.fysnet.net/yourhelp.htm the parity flag is only set in DOS 7.1+
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by susam on Sunday October 30, 2022 @04:44PM (#33398469)
I wrote this about 20 years ago during my university days. I happened to stumble upon it today in my archives and thought of sharing it on GitHub. I was still learning microprocessors back then. While browsing the C:\Windows directory, I fortuitously happened to discover the DEBUG.EXE program. Turned out it was available on any standard installation of MS-DOS 6.22 as well as Windows 98. That chance encounter helped me to dive into the world of assembly language programming much before the coursework introduced me to more popular assemblers.

Since I was still learning the x86 CPUs, the intention here was not to save bytes but instead to have something working. I believe I picked up the style of having the string at the top and jumping over it from other similar code I had come across in those days.

You are right of course. Here is a complete example that moves the string to the bottom and saves two bytes:

  C:\>DEBUG
  -A
  1165:0100 MOV AH, 9
  1165:0102 MOV DX, 10B
  1165:0105 INT 21
  1165:0107 MOV AH, 0
  1165:0109 INT 21
  1165:010B DB 'hello, world', D, A, '$'
  1165:011A
  -G
  hello, world

  Program terminated normally
  -N HELLO.COM
  -R CX
  CX 0000
  :1A
  -W
  Writing 0001A bytes
  -Q

  C:\>HELLO
  hello, world

  C:\>
I have now updated the GitHub repository with this updated source code and binary. Thank you for the nice comment!
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by owl57 on Sunday October 30, 2022 @04:57PM (#33398588)
Curious. These other programmers probably learned the habit from some even older code. Jumping over data isn't a very obvious way of organising code, so probably it served some purpose many years ago.

Maybe someone here knows what was that purpose?

Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by jstanley on Sunday October 30, 2022 @05:27PM (#33398905)
I wrote a compiler for a small machine that did this so that it could output the string content straight away without having to buffer it in memory.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by userbinator on Sunday October 30, 2022 @05:02PM (#33398648)
I remember seeing that in old Asm books too. My best guess is that it avoids having too many forward references, which would take up precious memory in the systems of the time and perhaps reach the limit of the assembler sooner.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by _the_inflator on Sunday October 30, 2022 @05:29PM (#33398924)
Maybe also better for linking the files. At least this was the reason I did it on Amiga when using absolute addresses. I only had to remember the start of the address area even when recompiling.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by bombcar on Sunday October 30, 2022 @08:20PM (#33400522)
This and the hard coding address comments are the key - forward looking references were expensive (and early enough, impossible) whereas you already knew where your data points were as they came before.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by jmole on Sunday October 30, 2022 @06:41PM (#33399744)
you can hard-code values if you know their address in memory. If the data section comes first, then it doesn't move around if your code size changes.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by lboc on Sunday October 30, 2022 @11:46PM (#33401834)
I've seen it done fairly often in mainframe assembler - embed an 'eyecatcher' string near the top of your program and jump to the real entry point. Used as an aid for debugging when reading dumps I believe. Not generally program data though, ususally metadata like program name, author, date assembled etc.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by kragen on Monday October 31, 2022 @12:34AM (#33402115)
A friend of mine used to program the PDP-8 a lot. The PDP-8 didn't have a stack; to call a subroutine, the JMS FOO instruction would store the return address at (the effective address computed from) FOO, then continue execution at the following word. So to return, the called subroutine would do an indirect jump using the address stored in the memory word before the beginning of its code.

I was surprised when he told me how people normally passed arguments. They would put them after the JMS instruction in the caller. So, the callee would indirect from the "return address" stored in FOO to retrieve its arguments, incrementing the return address after each one. So the code to call FOO with arguments 1 and 2 would be (in Intel syntax)

        JMS FOO
        DW 1
        DW 2
        [code to run after returning]
Mark Smotherman explains this in more detail, using PDP-8-compatible syntax, in https://people.computing.clemson.edu/~mark/subroutines/pdp8.....

It seems sort of intuitive to do things this way; if you're writing atan2(3, 4), it's nice to be able to translate this to

        jms    atan2
               3
               4
rather than, say, mov $3, %rdi; mov $4, %rsi; call atan2.

Maybe someone had this habit in their assembly and adapted it to the 8086's calling convention by inserting MOVs and a JMP instruction?

You can also imagine that a compiler might be somewhat simpler if it generated code in the order in which it encountered the expressions. Gas lets you switch back and forth between .text and .data, so that if your compiler does this, you still don't have to insert JMP instructions. However, a few years ago when I wrote Ur-Scheme, I did do this for lambda expressions: the code for the lambda expression is generated inline in the middle of its containing code, which then has to contain a jump past it.

Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by ale42 on Monday October 31, 2022 @07:31AM (#33404362)
One case where it has a use is on partition (or floppy disk) boot sectors. First instruction is a jump to skip the disk metadata (actually a BIOS parameter block), which is in a fixed place. See https://en.wikipedia.org/wiki/Volume_boot_record
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by Narishma on Sunday October 30, 2022 @05:15PM (#33398798)
DEBUG.EXE is present in all versions of MS-DOS since the very first.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by WelcomeShorty on Monday October 31, 2022 @08:34AM (#33404846)
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by Narishma on Wednesday November 02, 2022 @10:47PM (#33446325)
It was a .COM file back then but still the same program.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by donio on Sunday October 30, 2022 @04:55PM (#33398568)
debug.exe is single pass and doesn't do labels so by having the string first you know its address later.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by vore on Sunday October 30, 2022 @05:25PM (#33398890)
You can compute the address of the string yourself like a two-pass assembler would, though, so that shouldn't be limiting.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by pizza234 on Sunday October 30, 2022 @05:51PM (#33399167)
This is an ASM program with a very standard structure (including the standard printing API: http://spike.scu.edu.au/~barry/interrupts.html#ah09) using a very standard tool (DEBUG.exe, common at the time for quick debugging); I'm confused why this is impressive.
Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by alrlroipsp on Monday October 31, 2022 @06:22AM (#33403913)
Most if not all ANCIENT assembers did a 1-pass translation of input source and thus would not recognize tokens that was referenced but not yet declared.

Hence you declare your variables at the start of the program and jump past them.

Re:A 28-byte “hello, world” program assembled with DEBUG.EXE... by rep_lodsb on Monday October 31, 2022 @04:32PM (#33412576)
Any "real" assembler has to support forward references, otherwise you couldn't even jump past the initial data section, except by using an absolute address!

Minimizing the number of forward references may make the assembly run faster or use less memory, but usually it's just a convention to make the source code more neatly organized.