Image Map Image Map
Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 29

Thread: x86 assembly question: modifying flags register on the stack

  1. #11

    Default

    Quote Originally Posted by reenigne View Post
    How long does your interrupt handler take to run?
    It copies sectors from one memory location to another. Basically the following snippet times the number of sectors (which appears to be at most 2 during boot up, so far as I can tell):

    Code:
            MOV     CX, 0200h              ; copy 512 bytes
            REP     MOVSB
    Quote Originally Posted by Chuck(G)
    Is there any overwhelming reason to use POPF in that sequence? Can't you simply pop into any other register and modify the flag?
    Could try that. At the time I wrote the first function, I was too lazy to google which bit in the flags register was the carry flag. So I figured I'd just POPF/STC/PUSHF.

    Quote Originally Posted by Chuck(G)
    As far as saving the caller's flags, there's no particular reason to expect that on an INT 13H handler. The PC BIOS uses a RET 2.
    If that's what the PC BIOS does, then that's probably good enough for me. I looked around for the calling conventions of int13h. I found plenty of references on arguments and return values, but nothing on what registers and flags I could trash while handling the interrupt. I erred on the side of preserving everything.

  2. #12
    Join Date
    Jan 2007
    Location
    Pacific Northwest, USA
    Posts
    25,264
    Blog Entries
    20

    Default

    Just check the BIOS listing in the techref. I think it's still available on MZDs site.

  3. #13

    Default

    Quote Originally Posted by smbaker View Post
    It copies sectors from one memory location to another. Basically the following snippet times the number of sectors (which appears to be at most 2 during boot up, so far as I can tell):

    Code:
            MOV     CX, 0200h              ; copy 512 bytes
            REP     MOVSB
    On a 4.77MHz 8088 with no wait states and DRAM refresh at the normal 18 PIT cycles, REP MOVSB takes 4.5 PIT cycles per iteration, so 1024 bytes will take 4608 PIT cycles, so we'd expect to get a timer interrupt during that code about 7% of the time. However, if we're talking about bootup then the phase of the timer interrupt might be the same on entry to your handler every time it runs, so that might be the reason for the consistent behaviour.

  4. #14
    Join Date
    Jan 2007
    Location
    Pacific Northwest, USA
    Posts
    25,264
    Blog Entries
    20

    Default

    Stupid question: Why

    MOV CX,0200H
    REP MOVSB

    and not

    MOV CX,0200h/2
    REP MOVSW

    ?

  5. #15

    Default

    Quote Originally Posted by Chuck(G) View Post
    Stupid question: Why

    MOV CX,0200H
    REP MOVSB

    and not

    MOV CX,0200h/2
    REP MOVSW

    ?
    Honestly, I forgot there was a MOVSW. My brain told me to move 512 bytes, so I coded up a move of 512 bytes rather than 256 words. I'll make this change too!

  6. #16

    Default

    This ended up my final version,

    Code:
    iret_fuss_with_carry_flag:
            JC .carryset
            PUSH    BP
            MOV     BP, SP
            AND     BYTE [BP+6], 0FEh
            POP     BP
            IRET
    .carryset:
            PUSH    BP
            MOV     BP, SP
            OR      BYTE [BP+6], 1
            POP     BP
            IRET
    As far as I can tell, this works fine in DOS 3.10, DOS 3.21, and DOS 3.31.

    However, the Int 21h subfunction 13h, "delete File" causes the machine to hang in DOS 3.30. Only DOS 3.30 -- the other versions listed above work fine. Some investigation shows that "delete file" reads about a half dozen sectors (probably the FAT table and root directory) and then writes some of those sectors back out. Using a logic analyzer, I can get a little insight into what's going on. I can see the reads execute. For the last read, my iret_fuss_with_carry_flag function above executes, followed by the int 8 timer handler, which seems to do its thing adjusting counters in the BDA and reaches its IRET. Then the PC just stops executing instructions. We never make it to the write.

    If I wanted to force interrupts to be enabled by my IRET, when would "OR BYTE [BP+7], 2" do it?

    Scott

  7. #17
    Join Date
    Jan 2007
    Location
    Pacific Northwest, USA
    Posts
    25,264
    Blog Entries
    20

    Default

    Makes my "RET 2" solution look even better, doesn't it? You'd just EI before the "RET 2". No trying to figure out what bits in the stack copy do what.

  8. #18

    Default

    Quote Originally Posted by smbaker View Post
    Then the PC just stops executing instructions. We never make it to the write.
    The CPU will always be executing instructions unless it's waiting for the bus (DMA or wait state, which seems unlikely to be the problem here) or in a HLT state waiting for a hardware interrupt. Did the CPU execute a HLT right before it stopped executing instructions? If not, I think something else is going on here... What address did the IRET instruction remove from the stack? Did the CPU start fetching instruction bytes at that address? If so, what instructions do those bytes decode to?

    IRET is quite slow (44 cycles) - could it be that you just didn't capture enough data to see the CPU continue at the destination?

    Quote Originally Posted by smbaker View Post
    If I wanted to force interrupts to be enabled by my IRET, when would "OR BYTE [BP+7], 2" do it?
    Yes, but unless you understand what's going on and have determined that that is necessary to fix the problem, it's cargo cult programming.

  9. #19

    Default

    Quote Originally Posted by reenigne View Post
    The CPU will always be executing instructions unless it's waiting for the bus (DMA or wait state, which seems unlikely to be the problem here) or in a HLT state waiting for a hardware interrupt. Did the CPU execute a HLT right before it stopped executing instructions? If not, I think something else is going on here... What address did the IRET instruction remove from the stack? Did the CPU start fetching instruction bytes at that address? If so, what instructions do those bytes decode to?
    I only have a 16-channel logic analyzer (which I have set to look at the top 16 bits of the 20-bit address bus), and I'm pretty sure I'm losing some data because it's not able to sample at the full bandwidth of the CPU. So, the best I can do is to kind of get a feel for where it's running. I can see enough instruction fetches to get a good idea of what jumps it's following and what blocks of code it's executing, but I can't see the details of individual instructions or inspect the stack.

    Basically, we just seem to hit a point where we stop seeing transitions on the address bus on the logic analyzer. Since I'm not sampling the lower 4 bits of the address bus, it could be that we're in a very tight loop, though I don't see such a loop when inspecting the code in that block.

    I tried debugging it (i.e. with debug.com) but it fails on entry to the int 21h service routine.

    Quote Originally Posted by reenigne View Post
    Yes, but unless you understand what's going on and have determined that that is necessary to fix the problem, it's cargo cult programming.
    The best I have is a note I came across somewhere on the net that said some DOS versions expect the int 13h handler to return with interrupts enabled. There's also the int 13h handler for the floppy disk support in the BIOS I'm using, which does enable interrupts on exit. It pokes around in the stack, ANDing and ORing things similar to how I do it.

    Quote Originally Posted by Chuck(G)
    Makes my "RET 2" solution look even better, doesn't it?
    It does. I haven't tried it yet, but I will.

  10. #20

    Default

    Quote Originally Posted by Chuck(G) View Post
    Makes my "RET 2" solution look even better, doesn't it? You'd just EI before the "RET 2". No trying to figure out what bits in the stack copy do what.
    Modified to this:

    Code:
    iret_fuss_with_carry_flag:
            STI
            RETF    2
    As far as I can tell, no difference in behavior (aside from adding the STI), though it is a cleaner solution.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •