Some processors (Intel for one) put least significant byte first (little) in muli byte numeric types. Others put the most significant byte (big) first. In Latin based languages the left "end" is first and right "end" is last.
The FASTPROCs and text code will run in either PB For Windows 10 or PBCC 6. To use in older versions change ENDIAN32 to a FUNCTION and the others to SUBs. Test code a little moe effort due to TXT.WINDOW. Same to put in DLL (any language can use) or SLL. Knowledge of assembly not needed to use "as-is". An alternative is to replace FASTPROC and END FASTPROC with PUSHes and POPs of the register(s) used, and put "in-line". To have multiple calls in one procedure make into subroutines (label and RETURN).
LONG or DWORD
'file: EndianSwap32Fast.inc fastproc Endian32 (byval DwLg as long) as long ! mov ebx, DwLg ! bswap ebx ! mov DwLg, ebx end fastproc = DwLg
#compile exe #dim all #if %def(%pb_cc32)'ignore if PB for Windows #console off 'no console if PBCC #endif ' #include "EndianSwap32Fast.inc" function pbmain () as long local Lg as long local hTxtWin, Dwd, pByte as dword txt.window ("Test EndianSwap32", 20, 20, 20, 76) to hTxtWin Lg = -2 pByte = varptr(Lg) '----------------------------------------------------------------------------- txt.print hex$(Lg, 8) + " Windows numeric types are litte endian, but " + _ "HEX$() shows the Most" txt.print space$(9) + "Significant byte on left for us (i.e. big endian)." txt.print txt.color = &h0000C000 txt.print "Endian swap a LONG." txt.color = 0 txt.print hex$(peek(byte, pByte), 2); txt.print hex$(peek(byte, pByte + 1), 2); txt.print hex$(peek(byte, pByte + 2), 2); txt.print hex$(peek(byte, pByte + 3), 2) + " LONG -2 in little endian " + _ " byte-by-byte" Lg = Endian32(Lg) txt.print hex$(peek(byte, pByte), 2); txt.print hex$(peek(byte, pByte + 1), 2); txt.print hex$(peek(byte, pByte + 2), 2); txt.print hex$(peek(byte, pByte + 3), 2) + " LONG -2 in big endian " + _ "byte-by-byte" txt.print Dwd = 4026531841 pByte = varptr(Dwd) txt.color = &h0000C000 txt.print "Endian swap a DWORD. FASTPROC parameters are strickly LONGs, " + _ "but to BSWAP " txt.print "but to BSWAP they are just 4 bytes." txt.color = 0 txt.print hex$(peek(byte, pByte), 2); txt.print hex$(peek(byte, pByte + 1), 2); txt.print hex$(peek(byte, pByte + 2), 2); txt.print hex$(peek(byte, pByte + 3), 2) + " DWORD 4026531841 in little " + _ "endian byte-by-byte" Dwd = Endian32(Dwd) txt.print hex$(peek(byte, pByte), 2); txt.print hex$(peek(byte, pByte + 1), 2); txt.print hex$(peek(byte, pByte + 2), 2); txt.print hex$(peek(byte, pByte + 3), 2) + " DWORD 4026531841 in big " + _ "endian byte-by-byte" txt.print txt.color = &h0000C000 txt.print "Endian swapping is symmetrical. One procedure will work for " + _ "swaps in either" txt.print "direction (big to little or little to big)." txt.print txt.color = &h000000D0 txt.print "Any key to close." txt.waitkey$ end function
'File: EndianSwap64Fast.inc fastproc Endian64 (byval pQd as long) ! mov edi, pQd ! mov eax, [edi] ! mov ebx, [edi + 4] ! xchg al, [edi + 7] ! xchg ah, [edi + 6] ! shr eax, 16 ! xchg al, [edi + 5] ! xchg ah, [edi + 4] ! xchg bl, [edi + 3] ! xchg bh, [edi + 2] ! shr ebx, 16 ! xchg bl, [edi + 1] ! xchg bh, [edi] end fastproc
#compile exe #dim all #if %def(%pb_cc32)'ignore if PB for Windows #console off 'no console if PBCC #endif ' #include "EndianSwap64Fast.inc" function pbmain () as long local Qd as quad local hTxtWin, pQd as dword txt.window ("Test Endian64", 40, 40, 16, 64) to hTxtWin Qd = &h7000000320000001 pQd = varptr(Qd) '----------------------------------------------------------------------------- txt.print hex$(Qd, 16) + " HEX$() of whole quad 8070450545669701633." txt.print txt.color = &h0000C000 txt.print "byte-by-byte one byte HEX$ gives order of binary." txt.print "Endian swap a QUAD." txt.color = 0 txt.print hex$(peek(byte, pQd), 2); txt.print hex$(peek(byte, pQd + 1), 2); txt.print hex$(peek(byte, pQd + 2), 2); txt.print hex$(peek(byte, pQd + 3), 2); txt.print hex$(peek(byte, pQd + 4), 2); txt.print hex$(peek(byte, pQd + 5), 2); txt.print hex$(peek(byte, pQd + 6), 2); txt.print hex$(peek(byte, pQd + 7), 2) + " QUAD in little endian byte-by-byte." Endian64(pQd) txt.print hex$(peek(byte, pQd), 2); txt.print hex$(peek(byte, pQd + 1), 2); txt.print hex$(peek(byte, pQd + 2), 2); txt.print hex$(peek(byte, pQd + 3), 2); txt.print hex$(peek(byte, pQd + 4), 2); txt.print hex$(peek(byte, pQd + 5), 2); txt.print hex$(peek(byte, pQd + 6), 2); txt.print hex$(peek(byte, pQd + 7), 2) + " QUAD in big endian byte-by-byte." txt.print txt.print "The only input parameter is a pointer." txt.print txt.print "To leave original QUAD variable unchanged, set a" txt.print "another variable and pass its pointer to Endian64." txt.print txt.color = &h000000D0 txt.print "Any key to close." txt.waitkey$ end function
'File EndianSwap16Fast.inc fastproc Endian16 (byval pWd as long) ! mov eax, pWd ! mov bx, [eax] ! xchg bl, bh ! mov [eax], bx end fastproc
#compile exe #dim all #if %def(%pb_cc32)'ignore if PB for Windows #console off 'no console if PBCC #endif ' #include "File EndianSwap16Fast.inc" function pbmain () as long local WdInt as word local hTxtWin, pWdInt as dword txt.window ("Test Endian16", 40, 40, 16, 64) to hTxtWin WdInt = &hF001 pWDInt = varptr(WdInt) '----------------------------------------------------------------------------- txt.print hex$(WdInt, 4) + " HEX$() of whole word 61441." txt.print txt.color = &h0000C000 txt.print "byte-by-byte one byte HEX$ gives order of binary." txt.print "Endian swap a WORD." txt.color = 0 txt.print hex$(peek(byte, pWdInt), 2); txt.print hex$(peek(byte, pWdInt + 1), 2) + " WORD in little endian byte-by-byte." Endian16(pWdInt) txt.print hex$(peek(byte, pWdInt), 2); txt.print hex$(peek(byte, pWdInt + 1), 2) + " WORD in big endian byte-by-byte." txt.print txt.print "No test of INTEGER. Signed/unsigned tested in Endian32 demo." txt.print "The only input parameter is a pointer." txt.print txt.print "To leave original WORD/INTEGER variable unchanged, set a" txt.print "another variable and pass its pointer to Endian16." txt.print txt.color = &h000000D0 txt.print "Any key to close." txt.waitkey$ end function
File: EndianSwapX.inc fastproc EndianX (byval pX as long) ! mov edi, pX 'loop control ptr, dec from center each character ! mov ebx, edi 'when edi = ebx done ! mov edx, [edi - 4] 'string length ! mov ecx, edx ! and ecx, &h01??? '1 if length is odd ! shr edx, 1 '\ 2 'either odd or even ! add edi, edx 'below center ! dec edi 'to zero base ! mov esi, edi 'copy, to be adjusted to above center 'odd/even fork ! cmp ecx, 0 ! jnz X_IsOdd 'X_IsEven ! inc esi 'set to above center ! jmp LoopTop X_IsOdd: ! add esi, 2 'center not swapped, set to first above center 'Do the endian swap. LoopTop: ! mov al, [edi] 'byte of lower half to AL ! xchg al, [esi] 'swap AL with byte of upper half ! mov [edi], al 'AL back to byte of lower half ! cmp edi, ebx 'has first byte been swapped with last byte ! jz LoopDone ! inc esi 'adjust for next pass around loop ! dec edi ! jmp LoopTop LoopDone: end fastproc
#compile exe #dim all #if %def(%pb_cc32)'ignore if PB for Windows #console off 'no console if PBCC #endif ' #include "EndianSwapXFast.inc" function pbmain () as long local X as string local hTxtWin, pX, SzX as dword txt.window ("Test EndianX", 40, 40, 14, 62) to hTxtWin X = chr$(&h70,&h00,&h00,&h32,&h00,&h00,&h01) pX = strptr(X) '----------------------------------------------------------------------------- txt.print "To leave original string unchanged, copy to another" txt.print "string variable and pass its pointer to EndianX." txt.print txt.color = &h0000C000 txt.print "Odd number of bytes." txt.color = 0 txt.print hex$(peek(byte, pX), 2); txt.print hex$(peek(byte, pX + 1), 2); txt.print hex$(peek(byte, pX + 2), 2); txt.print hex$(peek(byte, pX + 3), 2); txt.print hex$(peek(byte, pX + 4), 2); txt.print hex$(peek(byte, pX + 5), 2); txt.print hex$(peek(byte, pX + 6), 2) + " 7 byte in big endian byte-by-byte." EndianX(pX) txt.print hex$(peek(byte, pX), 2); txt.print hex$(peek(byte, pX + 1), 2); txt.print hex$(peek(byte, pX + 2), 2); txt.print hex$(peek(byte, pX + 3), 2); txt.print hex$(peek(byte, pX + 4), 2); txt.print hex$(peek(byte, pX + 5), 2); txt.print hex$(peek(byte, pX + 6), 2)+ " 7 byte in little endian byte-by-byte." txt.print X = chr$(&h60,&h00,&h03,&h20,&h00,&h01) pX = strptr(X) txt.color = &h0000C000 txt.print "Even number of bytes." txt.color = 0 txt.print hex$(peek(byte, pX), 2); txt.print hex$(peek(byte, pX + 1), 2); txt.print hex$(peek(byte, pX + 2), 2); txt.print hex$(peek(byte, pX + 3), 2); txt.print hex$(peek(byte, pX + 4), 2); txt.print hex$(peek(byte, pX + 5), 2) + " 6 byte in big endian byte-by-byte." EndianX(pX) txt.print hex$(peek(byte, pX), 2); txt.print hex$(peek(byte, pX + 1), 2); txt.print hex$(peek(byte, pX + 2), 2); txt.print hex$(peek(byte, pX + 3), 2); txt.print hex$(peek(byte, pX + 4), 2); txt.print hex$(peek(byte, pX + 5), 2)+ " 6 byte in little endian byte-by-byte." txt.print txt.color = &h000000D0 txt.print "Any key to close." txt.waitkey$ end function
Created on 12 April 2025.
Source and compiled code partial copyleft (ↄ), the limitation is you
may not claim creation and attempt to copyright it.
Page text copyright © 2025, Dale Yarker.
To
Domain Home.![]() | To Dale's Notebook index.![]() | To Programs index.![]() |