• Michael Abrash‘s Graphics Programming Black Book--chapter1


    Michael Abrash's Graphics Programming Black Book--chapter1
    https://github.com/jagregory/abrash-black-book
    https://www.gamedev.net/tutorials/_/technical/graphics-programming-and-theory/graphics-programming-black-book-r1698/
    https://github.com/jagregory/abrash-black-book/blob/master/src/chapter-01.md
    LISTING 1.1 L1-1.C
    /*
    * Program to calculate the 16-bit checksum of all bytes in the
    * specified file. Obtains the bytes one at a time via read(),
    * letting DOS perform all data buffering.
    */
    a checksum of the WordPerfect version 4.2 thesaurus file, TH.WP (362,293 bytes in size)
    BC3.1的编译命令:bcc L1-1.C
    L1-1.exe wb.bmp -- 随便找了一个文件

    LISTING 1.2 L1-2.C
    /*
    * Program to calculate the 16-bit checksum of the stream of bytes
    * from the specified file. Obtains the bytes one at a time in
    * assembler, via direct calls to DOS.
    */
    LISTING 1.3 L1-3.ASM
    ; Assembler subroutine to perform a 16-bit checksum on the file
    ; opened on the passed-in handle. Stores the result in the
    ; passed-in checksum variable. Returns 1 for success, 0 for error.
    ;
    ; Call as:
    ;           int ChecksumFile(unsigned int Handle, unsigned int *Checksum);
    ;
    ; where:
    ;           Handle = handle # under which file to checksum is open
    ;           Checksum = pointer to unsigned int variable checksum is
    ;           to be stored in
    bcc L1-2.C L1-3.ASM
    L1-2.exe wb.bmp
    The checksum is: 11325  --- 运行明显比L1-1快一些

    LISTING 1.4 L1-4.C
    采用DOS调用,带缓冲区的,用getc()代替了read()
    /*
    * Program to calculate the 16-bit checksum of the stream of bytes
    * from the specified file. Obtains the bytes one at a time via
    * getc(), allowing C to perform data buffering.
    */
    bcc L1-4.C
    L1-4.exe wb.bmp
    明显又快了一些。

    LISTING 1.5 L1-5.C
    #define BUFFER_SIZE  0x8000   /* 32Kb data buffer */
    自己开一个32K缓冲区。换回read()
    /*
    * Program to calculate the 16-bit checksum of the stream of bytes
    * from the specified file. Buffers the bytes internally, rather
    * than letting C or DOS do the work.
    */
    bcc L1-5.C
    L1-5.exe wb.bmp
    速度又快了

    LISTING 1.6 L1-6.C
    /*
    * Program to calculate the 16-bit checksum of the stream of bytes
    * from the specified file. Buffers the bytes internally, rather
    * than letting C or DOS do the work, with the time-critical
    * portion of the code written in optimized assembler.
    */
    LISTING 1.7 L1-7.ASM

    ; Assembler subroutine to perform a 16-bit checksum on a block of
    ; bytes 1 to 64K in size. Adds checksum for block into passed-in
    ; checksum.
    ;
    ; Call as:
    ;     void ChecksumChunk(unsigned char *Buffer,
    ;     unsigned int BufferLength, unsigned int *Checksum);
    ;
    ; where:
    ;     Buffer = pointer to start of block of bytes to checksum
    ;     BufferLength = # of bytes to checksum (0 means 64K, not 0)
    ;     Checksum = pointer to unsigned int variable checksum is
    ;stored in
    ChecksumLoop:
          lodsb                  ;get the next byte
          add  dx,ax             ;add it into the checksum total
          loop ChecksumLoop      ;continue for all bytes in block
          mov  [bx],dx           ;save the new checksum
    lodsb速度很快,比c的循环Checksum += (unsigned int) *WorkingPtr++; 快
    bcc L1-6.C L1-7.ASM
    L1-6.exe wb.bmp      
    得到最快的版本。
    程序是逐步优化的,很经典的例子,虽然DOS比较老了,但是思想不老。

    附上各阶段程序

    L1-1.C

    1. /*
    2. * Program to calculate the 16-bit checksum of all bytes in the
    3. * specified file. Obtains the bytes one at a time via read(),
    4. * letting DOS perform all data buffering.
    5. */
    6. #include
    7. #include
    8. main(int argc, char *argv[]) {
    9. int Handle;
    10. unsigned char Byte;
    11. unsigned int Checksum;
    12. int ReadLength;
    13. if ( argc != 2 ) {
    14. printf("usage: checksum filename\n");
    15. exit(1);
    16. }
    17. if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) {
    18. printf("Can't open file: %s\n", argv[1]);
    19. exit(1);
    20. }
    21. /* Initialize the checksum accumulator */
    22. Checksum = 0;
    23. /* Add each byte in turn into the checksum accumulator */
    24. while ( (ReadLength = read(Handle, &Byte, sizeof(Byte))) > 0 ) {
    25. Checksum += (unsigned int) Byte;
    26. }
    27. if ( ReadLength == -1 ) {
    28. printf("Error reading file %s\n", argv[1]);
    29. exit(1);
    30. }
    31. /* Report the result */
    32. printf("The checksum is: %u\n", Checksum);
    33. exit(0);
    34. }

    L1-2.C L1-3.ASM

    1. /*
    2. * Program to calculate the 16-bit checksum of the stream of bytes
    3. * from the specified file. Obtains the bytes one at a time in
    4. * assembler, via direct calls to DOS.
    5. */
    6. #include
    7. #include
    8. main(int argc, char *argv[]) {
    9. int Handle;
    10. unsigned char Byte;
    11. unsigned int Checksum;
    12. int ReadLength;
    13. if ( argc != 2 ) {
    14. printf("usage: checksum filename\n");
    15. exit(1);
    16. }
    17. if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) {
    18. printf("Can't open file: %s\n", argv[1]);
    19. exit(1);
    20. }
    21. if ( !ChecksumFile(Handle, &Checksum) ) {
    22. printf("Error reading file %s\n", argv[1]);
    23. exit(1);
    24. }
    25. /* Report the result */
    26. printf("The checksum is: %u\n", Checksum);
    27. exit(0);
    28. }
    1. ; Assembler subroutine to perform a 16-bit checksum on the file
    2. ; opened on the passed-in handle. Stores the result in the
    3. ; passed-in checksum variable. Returns 1 for success, 0 for error.
    4. ;
    5. ; Call as:
    6. ; int ChecksumFile(unsigned int Handle, unsigned int *Checksum);
    7. ;
    8. ; where:
    9. ; Handle = handle # under which file to checksum is open
    10. ; Checksum = pointer to unsigned int variable checksum is
    11. ; to be stored in
    12. ;
    13. ; Parameter structure:
    14. ;
    15. Parms struc
    16. dw ? ;pushed BP
    17. dw ? ;return address
    18. Handle dw ?
    19. Checksum dw ?
    20. Parms ends
    21. ;
    22. .model small
    23. .data
    24. TempWord label word
    25. TempByte db ? ;each byte read by DOS will be stored here
    26. db 0 ;high byte of TempWord is always 0
    27. ;for 16-bit adds
    28. ;
    29. .code
    30. public _ChecksumFile
    31. _ChecksumFile proc near
    32. push bp
    33. mov bp,sp
    34. push si ;save C's register variable
    35. ;
    36. mov bx,[bp+Handle] ;get file handle
    37. sub si,si ;zero the checksum ;accumulator
    38. mov cx,1 ;request one byte on each ;read
    39. mov dx,offset TempByte ;point DX to the byte in
    40. ;which DOS should store
    41. ;each byte read
    42. ChecksumLoop:
    43. mov ah,3fh ;DOS read file function #
    44. int 21h ;read the byte
    45. jc ErrorEnd ;an error occurred
    46. and ax,ax ;any bytes read?
    47. jz Success ;no-end of file reached-we're done
    48. add si,[TempWord] ;add the byte into the
    49. ;checksum total
    50. jmp ChecksumLoop
    51. ErrorEnd:
    52. sub ax,ax ;error
    53. jmp short Done
    54. Success:
    55. mov bx,[bp+Checksum] ;point to the checksum variable
    56. mov [bx],si ;save the new checksum
    57. mov ax,1 ;success
    58. ;
    59. Done:
    60. pop si ;restore C's register variable
    61. pop bp
    62. ret
    63. _ChecksumFile endp
    64. end

    L1-4.C

    1. /*
    2. * Program to calculate the 16-bit checksum of the stream of bytes
    3. * from the specified file. Obtains the bytes one at a time via
    4. * getc(), allowing C to perform data buffering.
    5. */
    6. #include
    7. main(int argc, char *argv[]) {
    8. FILE *CheckFile;
    9. int Byte;
    10. unsigned int Checksum;
    11. if ( argc != 2 ) {
    12. printf("usage: checksum filename\n");
    13. exit(1);
    14. }
    15. if ( (CheckFile = fopen(argv[1], "rb")) == NULL ) {
    16. printf("Can't open file: %s\n", argv[1]);
    17. exit(1);
    18. }
    19. /* Initialize the checksum accumulator */
    20. Checksum = 0;
    21. /* Add each byte in turn into the checksum accumulator */
    22. while ( (Byte = getc(CheckFile)) != EOF ) {
    23. Checksum += (unsigned int) Byte;
    24. }
    25. /* Report the result */
    26. printf("The checksum is: %u\n", Checksum);
    27. exit(0);
    28. }

    L1-5.C

    1. /*
    2. * Program to calculate the 16-bit checksum of the stream of bytes
    3. * from the specified file. Buffers the bytes internally, rather
    4. * than letting C or DOS do the work.
    5. */
    6. #include
    7. #include
    8. #include /* alloc.h for Borland,
    9. malloc.h for Microsoft */
    10. #define BUFFER_SIZE 0x8000 /* 32Kb data buffer */
    11. main(int argc, char *argv[]) {
    12. int Handle;
    13. unsigned int Checksum;
    14. unsigned char *WorkingBuffer, *WorkingPtr;
    15. int WorkingLength, LengthCount;
    16. if ( argc != 2 ) {
    17. printf("usage: checksum filename\n");
    18. exit(1);
    19. }
    20. if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) {
    21. printf("Can't open file: %s\n", argv[1]);
    22. exit(1);
    23. }
    24. /* Get memory in which to buffer the data */
    25. if ( (WorkingBuffer = malloc(BUFFER_SIZE)) == NULL ) {
    26. printf("Can't get enough memory\n");
    27. exit(1);
    28. }
    29. /* Initialize the checksum accumulator */
    30. Checksum = 0;
    31. /* Process the file in BUFFER_SIZE chunks */
    32. do {
    33. if ( (WorkingLength = read(Handle, WorkingBuffer,
    34. BUFFER_SIZE)) == -1 ) {
    35. printf("Error reading file %s\n", argv[1]);
    36. exit(1);
    37. }
    38. /* Checksum this chunk */
    39. WorkingPtr = WorkingBuffer;
    40. LengthCount = WorkingLength;
    41. while ( LengthCount-- ) {
    42. /* Add each byte in turn into the checksum accumulator */
    43. Checksum += (unsigned int) *WorkingPtr++;
    44. }
    45. } while ( WorkingLength );
    46. /* Report the result */
    47. printf("The checksum is: %u\n", Checksum);
    48. exit(0);
    49. }

    L1-6.C L1-7.ASM

    1. /*
    2. * Program to calculate the 16-bit checksum of the stream of bytes
    3. * from the specified file. Buffers the bytes internally, rather
    4. * than letting C or DOS do the work, with the time-critical
    5. * portion of the code written in optimized assembler.
    6. */
    7. #include
    8. #include
    9. #include /* alloc.h for Borland,
    10. malloc.h for Microsoft */
    11. #define BUFFER_SIZE 0x8000 /* 32K data buffer */
    12. main(int argc, char *argv[]) {
    13. int Handle;
    14. unsigned int Checksum;
    15. unsigned char *WorkingBuffer;
    16. int WorkingLength;
    17. if ( argc != 2 ) {
    18. printf("usage: checksum filename\n");
    19. exit(1);
    20. }
    21. if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) {
    22. printf("Can't open file: %s\n", argv[1]);
    23. exit(1);
    24. }
    25. /* Get memory in which to buffer the data */
    26. if ( (WorkingBuffer = malloc(BUFFER_SIZE)) == NULL ) {
    27. printf("Can't get enough memory\n");
    28. exit(1);
    29. }
    30. /* Initialize the checksum accumulator */
    31. Checksum = 0;
    32. /* Process the file in 32K chunks */
    33. do {
    34. if ( (WorkingLength = read(Handle, WorkingBuffer,
    35. BUFFER_SIZE)) == -1 ) {
    36. printf("Error reading file %s\n", argv[1]);
    37. exit(1);
    38. }
    39. /* Checksum this chunk if there's anything in it */
    40. if ( WorkingLength )
    41. ChecksumChunk(WorkingBuffer, WorkingLength, &Checksum);
    42. } while ( WorkingLength );
    43. /* Report the result */
    44. printf("The checksum is: %u\n", Checksum);
    45. exit(0);
    46. }
    1. ; Assembler subroutine to perform a 16-bit checksum on a block of
    2. ; bytes 1 to 64K in size. Adds checksum for block into passed-in
    3. ; checksum.
    4. ;
    5. ; Call as:
    6. ; void ChecksumChunk(unsigned char *Buffer,
    7. ; unsigned int BufferLength, unsigned int *Checksum);
    8. ;
    9. ; where:
    10. ; Buffer = pointer to start of block of bytes to checksum
    11. ; BufferLength = # of bytes to checksum (0 means 64K, not 0)
    12. ; Checksum = pointer to unsigned int variable checksum is
    13. ;stored in
    14. ;
    15. ; Parameter structure:
    16. ;
    17. Parms struc
    18. dw ? ;pushed BP
    19. dw ? ;return address
    20. Buffer dw ?
    21. BufferLength dw ?
    22. Checksum dw ?
    23. Parms ends
    24. ;
    25. .model small
    26. .code
    27. public _ChecksumChunk
    28. _ChecksumChunk proc near
    29. push bp
    30. mov bp,sp
    31. push si ;save C's register variable
    32. ;
    33. cld ;make LODSB increment SI
    34. mov si,[bp+Buffer] ;point to buffer
    35. mov cx,[bp+BufferLength] ;get buffer length
    36. mov bx,[bp+Checksum] ;point to checksum variable
    37. mov dx,[bx] ;get the current checksum
    38. sub ah,ah ;so AX will be a 16-bit value after LODSB
    39. ChecksumLoop:
    40. lodsb ;get the next byte
    41. add dx,ax ;add it into the checksum total
    42. loop ChecksumLoop ;continue for all bytes in block
    43. mov [bx],dx ;save the new checksum
    44. ;
    45. pop si ;restore C's register variable
    46. pop bp
    47. ret
    48. _ChecksumChunk endp
    49. end

  • 相关阅读:
    C#通过中序遍历对二叉树进行线索化
    想免费用虚拟手机号注册网站、买买买或接验证码?
    python04- 函数、time
    Python----科学计数法、同时给多个变量赋值、eval函数、math库函数、复数(complex())、内置的数值运算函数、内置的数值运算操作符
    python实现ftp服务端和客户端
    Python pathlib模块
    创新科技改变城市:智慧城市建设全景展望
    创建型模式-单例模式
    Apache Atlas 是什么?
    物联网AI MicroPython传感器学习 之 TEA5767 FM收音机模块
  • 原文地址:https://blog.csdn.net/hb_zxl/article/details/126843617