News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Help with Bubble Sorting in MASM

Started by MASMClass, May 11, 2014, 08:05:57 AM

Previous topic - Next topic

Gunther

Will,

Quote from: Will on May 25, 2014, 11:38:20 PM
... and it'll be the same in MAS32. What we are talking about here is that I have to set the ES:EDI registers to point to the ADAM .data and the DS:ESI to the user .data when writing a record for the user and the opposite when reading a record for the user.

No. Don't touch the segment registers under a Protected Mode Operating System. You have to point ESI to the source and EDI to the destination. That's all. It's high time to understand that.

Gunther
You have to know the facts before you can distort them.

Will

Quote from: Gunther on May 26, 2014, 12:47:57 AM
Will,

No. Don't touch the segment registers under a Protected Mode Operating System. You have to point ESI to the source and EDI to the destination. That's all. It's high time to understand that.

Gunther

Gunther:

What you don't seem to understand is that if you call ADAM you had better be in the same protected mode memory as ADAM is. You link them together and that will take care of the problem. Back in 1982 there was no memory protect mode but I still had to work out how to call ADAM from a program. I had to figure out how to adjust the ES and DS registers so the string move instructions would work properly. You also don't seem to know that for years starting in 1969, long before PCs were around, I "Systems Programmed" on the IBM 360 system which was a 32 bit memory protected machine. I don't think that, without that experience, I ever could have written ADAM. Talk to an IBM assembler language programmer and you'll find out that the new PC architecture  is very similar to the IBM mainframe architecture from way before the PC X86 processors were even thought of.  8)

Gunther

Will,

Quote from: Will on May 26, 2014, 01:15:58 AM
Gunther:

What you don't seem to understand is that if you call ADAM you had better be in the same protected mode memory as ADAM is.

the question is: Do you understand what I'm talking about?

Do you really think you're the only mainframe programmer in the world? Hutch and me - and probably others too - did start the career as coder with mainframe programming. It's true that a lot of principles are adopted from mainframes to the todays PCs. But there are a lot of principle differences, too. The IBM 360 series was a CISC computer with 16 32-bit registers and 4 64-bit floating point registers as a time-sharing system. It was first MFT (Multiprogramming with a fixed number of tasks) and became later a MVT (Multiprogramming with a variable number of tasks). But that was another approach.

You don't know not much about Protected Mode. The trick is: All your code and data are inside the same segment (memory range). As a beginner you should not touch the segment registers. That's what we've written to you several times: for example here and here. But you should follow that hints and read that stuff, at least.

Gunther
You have to know the facts before you can distort them.

dedndave

what Will is missing is the fact that his old code had a 640 Kb limit
and, under win32, we might move more than 640 Kb from one place to another inside a single workspace   :P

you can play with DS and ES if you like, but be prepared for a crashing program
the only "segment register" i have had to deal with under win32 is FS
and, then, i haven't had to modify it - just change the ASSUME   :biggrin:

RuiLoureiro

Hi Will

    You say:
Quote
                «I have to set the ES:EDI registers to point to the ADAM .data
                and
                the DS:ESI to the user .data when writing a record for the user
                and
                the opposite when reading a record for the user»
It seems that you think that ES:EDI registers to point to
        "a protected memory" the ADAM .data.
        and
        the DS:ESI to "an unprotected memory" the user .data.
                   
        One question: What's the problem if ES=DS ?
        Could you explain ?

RuiLoureiro

Hi Will,

Quote
How I sorted records using ADAM was
to build a record with a key

in the order that I wanted it sorted,
created an ADAM file using ADAMCREA.exe with that key,
added the records

I built in random order to the ADAM file using ADAMACMD, and then read them back
in sequential order because  ADAM has them all sorted by key.

            It seems that:
           
                1. When we want to create a database, we put the records
                   one after another.

                2. When we want to search for ...???... we use ADAMCREA.exe
                   etc. etc. and then we have it sorted.

                3. And we may show it...

            Is this correct, Will ?
            If it is correct, i would say that i never would use it.

Will

Quote from: Gunther on May 26, 2014, 01:43:26 AM
Will,

Quote from: Will on May 26, 2014, 01:15:58 AM
Gunther:

What you don't seem to understand is that if you call ADAM you had better be in the same protected mode memory as ADAM is.

the question is: Do you understand what I'm talking about?

You don't know not much about Protected Mode. The trick is: All your code and data are inside the same segment (memory range). As a beginner you should not touch the segment registers.
Gunther

Gunther - Isn't that what I said? when you link one of the ADAM subroutines with a program that uses it, you link them together as in the following:

LINK /SUBSYSTEM:CONSOLE myprogram ADAM(SUBROUTINE) ENTRY:(myprogram entry point)

If I get everything for my line editor converted to MASM32 it will be linked as follows:

LINK /SUBSYSTEM:CONSOLE EDLINAS ADAMACRM ADAMALDM ADAMACMD /ENTRY:BEGIN (BEGIN IS THE ENTRY POINT TO EDLINAS, my line editor).

That way all of myprogram and all of the ADAM subroutine are in the same memory "segment" so protected memory is not a problem. I've already encountered the problem and spent a day figuring out that "The program has encountered a problem and needs to close" meant what would be called a "protection exception" on a mainframe. (I accidentally accessed memory that was not in the same memory "segment" as my program.)

Will

Quote from: RuiLoureiro on May 26, 2014, 04:22:02 AM
Hi Will,
            It seems that:
           
                1. When we want to create a database, we put the records
                   one after another.

                2. When we want to search for ...???... we use ADAMCREA.exe
                   etc. etc. and then we have it sorted.

                3. And we may show it...

            Is this correct, Will ?
            If it is correct, i would say that i never would use it.

Ruil: not exactly.
                           1 - Use ADAMCREA.exe to create the ADAM file with a key that you want to sort records into.
                           2 - Use a program to call ADAMACMD to add the records in random order by the key    sequence that you want them sorted into.
                           3 - Use ADAMACMD to read them back in the sequential order that you wanted to sort them                                           into.
                    and 4 - If you want, you can read, write, add, and/or erase records in random, forward, or backward order .  :t

RuiLoureiro

Will,
         I hope you translate your DOS to WIN32 and post it here.
         I would like to read it... and i would like
         to see how it works.
         The names itself never say anything to me.
         That's all.  :t

Gunther

Will,

Quote from: Will on May 26, 2014, 05:40:55 AM
LINK /SUBSYSTEM:CONSOLE myprogram ADAM(SUBROUTINE) ENTRY:(myprogram entry point)

that's exactly the point. With SUBSYSTEM:CONSOLE your application is a 32-bit Protected Mode console application. That is: DS = ES (contain the same selector, which is a pointer to a segment descriptor). The only thing what you've to do is to change ESI and EDI, not more, because DS and ES have already the appropriate value. That was my point.

Gunther
You have to know the facts before you can distort them.

Will

Quote from: Gunther on May 26, 2014, 07:59:53 AM
Will,

Quote from: Will on May 26, 2014, 05:40:55 AM
LINK /SUBSYSTEM:CONSOLE myprogram ADAM(SUBROUTINE) ENTRY:(myprogram entry point)

that's exactly the point. With SUBSYSTEM:CONSOLE your application is a 32-bit Protected Mode console application. That is: DS = ES (contain the same selector, which is a pointer to a segment descriptor). The only thing what you've to do is to change ESI and EDI, not more, because DS and ES have already the appropriate value. That was my point.

Gunther

Gunther - the way that ADAM operates on a DOS system is similar to the way it will operate on a Win32 system It gets it's memory with an interrupt on the DOS system and will have to get memory on the Win32 system using "heap" functions. I designed it originally to use available memory to do it's thing. I'll have to do the same with Win32 according to my reading. Anyway, in most programs, the DS and ES registers point to the same date area. When you call ADAM to create, load, or access a file it has to get memory. The result is that the ES and  DS registers have to be manipulated to move records and other information from and to the users memory with the ES:DI and DS:SI registersunder DOS. Under Win32 it will use the ES:EDI and DS:ESI registers. the ES and DS registers are changed depending on whether ADAM is moving information to or from the users .data. I did it that way back when I was writing version 1 of ADAM. The same thing applies to verson 2 on Win32. Now, after over twenty years, I'm converting ADAM from DOS 16 bit to MASM 32 bit. Don't worry, I know what I'm doing and I'll thoroughly test it before I allow anybody to use it.  8)

Will

Quote from: RuiLoureiro on May 26, 2014, 06:38:37 AM
Will,
         I hope you translate your DOS to WIN32 and post it here.
         I would like to read it... and i would like
         to see how it works.
         The names itself never say anything to me.
         That's all.  :t

How it works is a trade secret that I plan to keep to myself. What it will do, I've tried to explain to people. Let's just say that if you need something to create a data base system, it's the best there is. Unfortunately, I've been distracted now for over twenty years so I've just recently gotten around to converting it to 32 bit code. I'm even looking ahead and expect that, if things go right, version 3 will be a 64 bit data base system and those who have "Cloud" compuying systms will have a real competitor.  :t

dedndave

i can well imagine it goes something like this...

you pass a segment
the base offset (SI or DI) is 0, resulting in a SEG:0 arrangement

eventually, you'll have convert those terms into a base address that is not 0   :P
you can trust me on this

MichaelW

#43
Quote from: Will on May 26, 2014, 09:57:35 AM
When you call ADAM to create, load, or access a file it has to get memory. The result is that the ES and  DS registers have to be manipulated to move records and other information from and to the users memory with the ES:DI and DS:SI registers under DOS. Under Win32 it will use the ES:EDI and DS:ESI registers. the ES and DS registers are changed depending on whether ADAM is moving information to or from the users .data.

In a Windows application any attempt to load anything other than a valid selector (or a null selector, but that presents other problems) into a segment register will trigger an exception, and Windows will solve the problem by terminating your application.

Demo.asm:

;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
    .data
    .code
;==============================================================================
start:
;==============================================================================
    ; Display the selector in DS and ES:
    mov bx, es
    movzx ebx, bx
    printf("%04Xh\n",ebx)
    mov ax, es
    movzx eax, ax
    printf("%04Xh\n",eax)
    ; Increment the selector value and display it:
    inc ebx
    printf("%04Xh\n",ebx)
    inkey "Press any key to trigger an exception..."
    ; Now try to load the selector into ES:
    mov es, bx
;==============================================================================
end start


0023h
0023h
0024h
Press any key to trigger an exception...


The above shows that DS and ES have the same selector, so they both have the same segment base, limit, and access rights, and therefore can be used to access anywhere in the accessible address space.

And here are the essential parts of the DrWatson crash dump:

Application exception occurred:
        App: C:\masm32\My\NewSegRegs\demo.exe (pid=2580)
        When: 5/26/2014 @ 00:53:59.079
        Exception number: c0000005 (access violation)

*----> System Information <----*
...
*----> Task List <----*
...
2580 demo.exe
196 drwtsn32.exe
*----> Module List <----*
(0000000000400000 - 0000000000404000: C:\masm32\My\NewSegRegs\demo.exe
(0000000077b40000 - 0000000077b62000: C:\WINDOWS\system32\Apphelp.dll
(0000000077c00000 - 0000000077c08000: C:\WINDOWS\system32\VERSION.dll
(0000000077c10000 - 0000000077c68000: C:\WINDOWS\system32\msvcrt.dll
(0000000077dd0000 - 0000000077e6b000: C:\WINDOWS\system32\ADVAPI32.dll
(0000000077e70000 - 0000000077f03000: C:\WINDOWS\system32\RPCRT4.dll
(0000000077f10000 - 0000000077f59000: C:\WINDOWS\system32\GDI32.dll
(0000000077f60000 - 0000000077fd6000: C:\WINDOWS\system32\SHLWAPI.dll
(0000000077fe0000 - 0000000077ff1000: C:\WINDOWS\system32\Secur32.dll
(000000007c800000 - 000000007c8f6000: C:\WINDOWS\system32\kernel32.dll
(000000007c900000 - 000000007c9b2000: C:\WINDOWS\system32\ntdll.dll
(000000007e410000 - 000000007e4a1000: C:\WINDOWS\system32\USER32.dll

*----> State Dump for Thread Id 0x8f8 <----*

eax=00000002 ebx=00000024 ecx=7c81138e edx=7c90e514 esi=00340036 edi=00320035
eip=00401053 esp=0012ffc4 ebp=0012fff0 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

*** WARNING: Unable to verify checksum for C:\masm32\My\NewSegRegs\demo.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\masm32\My\NewSegRegs\demo.exe
function: demo
        0040102d 1030             adc     [eax],dh
        0040102f 40               inc     eax
        00401030 00ff             add     bh,bh
        00401032 151c204000       adc     eax,0x40201c
        00401037 83c408           add     esp,0x8
        0040103a 6818304000       push    0x403018
        0040103f e814000000       call    demo+0x1058 (00401058)
        00401044 e847000000       call    demo+0x1090 (00401090)
        00401049 6841304000       push    0x403041
        0040104e e805000000       call    demo+0x1058 (00401058)
FAULT ->00401053 668ec3           mov     es,bx
        00401056 cc               int     3
        00401057 cc               int     3
        00401058 55               push    ebp
        00401059 8bec             mov     ebp,esp
        0040105b 83c4f4           add     esp,0xfffffff4
        0040105e 6af5             push    0xf5
        00401060 e8cd000000       call    demo+0x1132 (00401132)
        00401065 8945fc           mov     [ebp-0x4],eax
        00401068 ff7508           push    dword ptr [ebp+0x8]
        0040106b e850000000       call    demo+0x10c0 (004010c0)


So given that the DS and ES (and also SS) segment registers all "point" to the same segment, when manipulating data there is no need to modify or even specify a segment register. And while MOVS_ and similar instructions are hardwired to use ESI and EDI, in 32-bit code (or 16-bit code using 32-bit instructions) indirect memory operands can use any general-purpose register as a base register or an index register.

;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
HEXDUMP MACRO address, paragraphs, zerobase
    invoke HexAsciiDump, address, paragraphs, zerobase
ENDM
hexdump equ HEXDUMP
;==============================================================================
    .data
    .code
;==============================================================================
;-----------------------------------------------------------------------
; This longer name avoids a conflict with the MASM32 HexDump procedure.
;-----------------------------------------------------------------------
HexAsciiDump proc startAddress:DWORD, nParagraphs:DWORD, fZeroBase:DWORD
    push ebx
    push edi
    push esi
    mov esi, startAddress
    xor ebx, ebx
    .WHILE ebx < nParagraphs
        mov eax, esi
        mov ecx, ebx
        shl ecx, 4
        .IF fZeroBase
            printf( "%08X  ", ecx )
        .ELSE
            add eax, ecx
            printf( "%08X  ", eax )
        .ENDIF
        xor edi, edi
        .WHILE edi < 16
            mov ecx, ebx
            shl ecx, 4
            add ecx, edi
            movzx eax, BYTE PTR [esi+ecx]
            printf( "%02X ", eax )
            .IF edi == 7
                printf( "- " )
            .ENDIF
            inc edi
        .ENDW
        printf( "  " )
        xor edi, edi
        .WHILE edi < 16
            mov ecx, ebx
            shl ecx, 4
            add ecx, edi
            movzx eax, BYTE PTR [esi+ecx]
            .IF eax > 31 && eax < 127
                printf( "%c", eax )
            .ELSE
                printf( "." )
            .ENDIF
            inc edi
        .ENDW
        printf( "\n" )
        inc ebx
    .ENDW
    pop esi
    pop edi
    pop ebx
    ret
HexAsciiDump endp
;==============================================================================
start:
;==============================================================================
    invoke GetProcessHeap
    mov ebx, eax

    invoke HeapAlloc, ebx, HEAP_ZERO_MEMORY, 16
    mov esi, eax
    hexdump esi, 1, 0

    invoke HeapAlloc, ebx, HEAP_ZERO_MEMORY, 16
    mov edi, eax
    hexdump edi, 1, 0

    xor eax, eax
    mov ecx, 16
  @@:
    dec ecx
    mov [esi+ecx], cl
    jnz @B
    hexdump esi, 1, 0

    push esi
    push edi
    mov ecx, 16
    rep movsb
    pop edi
    pop esi
    hexdump edi, 1, 0

    mov edx, edi
    mov ecx, 15
  @@:
    add BYTE PTR [edx+ecx], 1
    dec ecx
    jns @B
    hexdump edx, 1, 0

    mov edx, esi
    mov eax, -1
    mov ecx, 4
  @@:
    dec ecx
    mov [edx+ecx*4], eax
    jnz @B
    hexdump edx, 1, 0

    printf("\n")

    invoke HeapFree, ebx, 0, esi
    invoke HeapFree, ebx, 0, edi

    inkey
    exit
;==============================================================================
end start


001432D8  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00   ................
001432F0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00   ................
001432D8  00 01 02 03 04 05 06 07 - 08 09 0A 0B 0C 0D 0E 0F   ................
001432F0  00 01 02 03 04 05 06 07 - 08 09 0A 0B 0C 0D 0E 0F   ................
001432F0  01 02 03 04 05 06 07 08 - 09 0A 0B 0C 0D 0E 0F 10   ................
001432D8  FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF   ................


Well Microsoft, here's another nice mess you've gotten us into.

Gunther

Quote from: MichaelW on May 26, 2014, 04:08:54 PM
In a Windows application any attempt to load anything other than a valid selector (or a null selector, but that presents other problems) into a segment register will trigger an exception, and Windows will solve the problem by terminating your application.

that's exactly what will happen. But please ignore us, Will, it's your freedom.

But let me say this: It isn't necessary to change a segment register. You don't know what Protected Mode is, you  know nothing about Protected Mode principles, behavior, the ring concept etc. etc. But you would like to change segment registers? Fine, good luck.

Gunther
You have to know the facts before you can distort them.