8
\$\begingroup\$

The following 8088/8086 assembly program tests the modular-sum checksum of a block of data. I suspect it could be tighter; can anyone do it in fewer bytes?

31        xor        ax,ax          ; zero the sum
c0
bb        mov        bx,2000h        ; count 8kb of ROM
00
20
4b        dec        bx             ; start at the top
02        add        al,[bx]        ; add the current byte to the total
07
85        test       bx,bx          ; see if we're at the bottom yet
db
75        jnz        -7             ; loop while not done
f9
84        test       al,al          ; sum should be 0
c0
74        jz         1              ; if sum is good, continue with program
01
f4        hlt                       ; if sum is bad, stop
\$\endgroup\$
13
  • \$\begingroup\$ If that is intended to check 8k, shouldn't that be 2000h instead of just 2000? Also, you could rework the code to use the flags that get set by dec to figure out if you should keep looping rather than doing test. \$\endgroup\$ Jun 4 '17 at 3:40
  • 1
    \$\begingroup\$ Why do you have to do cld? Is there unknown code that executes before this that has a habit of changing and not restoring this? I'd certainly expect the power-on default for any 8086 chip to be cld. \$\endgroup\$ Jun 5 '17 at 1:06
  • 1
    \$\begingroup\$ I'd say not. Code like this is often reused and having cld versus omitting it means that you trade off a single byte for the potential future pain of having things run just fine most of the time until some other function is called that changes the direction flag before this code is invoked. Good luck untangling that runtime nightmare. I'd rather pay the price for the byte and the additional clarity, but that's just me. \$\endgroup\$
    – Edward
    Jun 5 '17 at 15:46
  • 2
    \$\begingroup\$ Please do not modify the question to reflect changes made in response to answers or comments. Those changes would actually make the answers invalid. This is site policy. If you want a review of your updated code, you have to ask a new question. \$\endgroup\$ Jun 5 '17 at 15:52
  • 1
    \$\begingroup\$ "Am I being too cautious?" - I'd say it depends on your environment. If you can feel confident about the code that is being executed before you and are desperate for that 1 more byte... \$\endgroup\$ Jun 5 '17 at 21:55
5
\$\begingroup\$

I'm not absolutely certain (I haven't run it through an assembler or checked against an instruction chart), but I believe this may be a byte shorter:

    xor dl, dl    
    xor si, si    
    mov cx, 2000h         
again:
    lodsb       ; load value, increment SI
    add dl, al  ; set z flag based on result of addition
    loop again  ; decrement CX, jump if NZ, *without* affecting flags

    jz good     ; Z flag still has result of addition above
    hlt
good:
\$\endgroup\$
12
  • \$\begingroup\$ Are you sure about that comma after loop? \$\endgroup\$ Jun 4 '17 at 12:21
  • \$\begingroup\$ This might need a cld instruction to assure that lodsb increments SI. \$\endgroup\$
    – Edward
    Jun 4 '17 at 12:49
  • 1
    \$\begingroup\$ @Edward: well, it should probably at least have a comment saying that it assumes the D flag is clear (but unless otherwise specified, that is normally a pretty safe assumption). \$\endgroup\$ Jun 4 '17 at 16:04
  • \$\begingroup\$ @DavidWohlferd: Oops. Yes, at least with most assemblers that would be wrong. \$\endgroup\$ Jun 4 '17 at 16:06
  • \$\begingroup\$ I think it's actually two bytes shorter than the original, and a byte shorter than David's modification, but that's without the cld. \$\endgroup\$ Jun 4 '17 at 19:32
1
\$\begingroup\$

To answer my own question, this version (which incorporates suggestions from David Wohlferd in the comments) is one byte shorter:

a0      mov     al,[0000h]      ; the loop skips byte 0000, so add it here
00
00
bb      mov     bx,1fffh        ; count 8kb of ROM
ff
1f
02      add     al,[bx]         ; add current byte to the total, top->bottom
07
4b      dec     bx
75      jnz     -5              ; loop while not done
fb
84      test    al,al           ; sum should be 0
c0
74      jz      1               ; if sum is good, continue with program
01
f4      hlt                     ; if sum is bad, stop
\$\endgroup\$
5
  • \$\begingroup\$ I was going to recommend using xor al, al to clear the register (some processors optimize for that), but I wonder if mov al, ds:1fff would work? I suspect it wouldn't save you (or cost you) any bytes, but it would reduce the number of loops needed by 1 (mov bx, 1ffeh). \$\endgroup\$ Jun 4 '17 at 12:15
  • \$\begingroup\$ The 8088 certainly doesn't optimize for XOR to clear registers. It doesn't have register renaming, and doesn't need to break any dependencies. It isn't nearly that complicated of a chip. :-) Of course, XOR to clear a register is still preferable over MOV because it is 1 byte shorter! And reducing the code size, as you appear to already know, is a big deal when optimizing for the 8088. (And 386SX.) \$\endgroup\$
    – Cody Gray
    Jun 7 '17 at 12:25
  • \$\begingroup\$ By the way, just as a code style thing, I would strongly encourage you to use labels as branch targets, rather than hard-coding numerical offsets. Not only does this make the code easier to read at a glance, without having to count bytes, but the numerical offsets are kind of ambiguous, since many assemblers tend to represent them differently than Intel's documentation does. It doesn't change the size of the code or anything to use labels; the assembler will generate identical code. \$\endgroup\$
    – Cody Gray
    Jun 7 '17 at 12:27
  • \$\begingroup\$ Thanks for the feedback. I'm still learning assembly language, and I haven't actually had to use an assembler yet. I just type the bytecodes directly into a file with a hex editor. I'm getting pretty good at reading the raw hex. \$\endgroup\$ Jun 7 '17 at 21:29
  • \$\begingroup\$ Ah, I see. Well then you are more hardcore than me. :-) Do consider using an assembler and making your life easier. Writing quality, readable assembly code is hard enough. Doing it with a hex editor is just masochism. On retro machines, MASM and TASM are excellent options, usually available on "abandonware" sites. I don't personally see any ethical problems with that, especially with MASM if you own a modern license for a Microsoft development product like Visual Studio. If you prefer free software, NASM and YASM are also excellent choices, and you can do retro-dev from a modern box. \$\endgroup\$
    – Cody Gray
    Jun 8 '17 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.