日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

lcd取模如何取16位_两种方式实现取16位变量的高低8位, 不严谨对比

發布時間:2023/12/20 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lcd取模如何取16位_两种方式实现取16位变量的高低8位, 不严谨对比 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

程序如下,第一種方式是強制指針轉換,再取結構體成員;第二種方式是簡單的移位。前面這種寫法得考慮大小端序, 后者不用管.

#include <stdio.h>#define hi8(x) ((( struct { unsigned char l; unsigned char h; } *)(&x))->h) #define lo8(x) ((( struct { unsigned char l; unsigned char h; } *)(&x))->l) #define hi8a(x) (((x) >> 8) & 0xff) #define lo8a(x) ((x) & 0xff)int main(void) {unsigned short x;scanf("%4x", &x); // 不能用字面量測試, 否則-Os編譯時會直接給求值了printf("%2X %2Xn", hi8(x), lo8(x));printf("%2X %2Xn", hi8a(x), lo8a(x));return 0; }

分別用mingw-gcc, arm-none-eabi-gcc, -O0和-Os選項編譯,得到的匯編如下(只取scanf到第二次printf之間的部分)

mingw-gcc, -O0, 前者9條指令, 后者10條指令. 有點呆萌是吧...

call _scanflea eax, [esp+30]movzx eax, BYTE PTR [eax]movzx edx, allea eax, [esp+30]movzx eax, BYTE PTR [eax+1] ; 這里錯開1字節取值movzx eax, almov DWORD PTR [esp+8], edxmov DWORD PTR [esp+4], eaxmov DWORD PTR [esp], OFFSET FLAT:LC1 ; LC1是printf的格式字符串call _printfmovzx eax, WORD PTR [esp+30]movzx eax, axmovzx edx, almovzx eax, WORD PTR [esp+30]shr ax, 8 ; 移位movzx eax, axmovzx eax, almov DWORD PTR [esp+8], edxmov DWORD PTR [esp+4], eaxmov DWORD PTR [esp], OFFSET FLAT:LC1call _printf

mingw-gcc, -Os, 前者5條指令, 后者6條指令.

call _scanfmovzx eax, BYTE PTR [esp+30]mov DWORD PTR [esp], OFFSET FLAT:LC1 ; 常量入棧提到前面了mov DWORD PTR [esp+8], eaxmovzx eax, BYTE PTR [esp+31] ; 取值錯開1字節mov DWORD PTR [esp+4], eaxcall _printfmov ax, WORD PTR [esp+30]mov DWORD PTR [esp], OFFSET FLAT:LC1movzx edx, almovzx eax, ah ; 這次把移位優化掉了, 直接利用ax寄存器的高低位.mov DWORD PTR [esp+8], edxmov DWORD PTR [esp+4], eaxcall _printf

arm-none-eabi-gcc, -O0, 前者8條指令, 后者10條指令:

bl scanfsub r3, fp, #6ldrb r3, [r3, #1] @ zero_extendqisi2mov r2, r3sub r3, fp, #6ldrb r3, [r3] @ zero_extendqisi2 ; 錯開1字節ldr r0, .L3+4 ; .L3+4是printf的格式字符串mov r1, r2mov r2, r3bl printfldrh r3, [fp, #-6]mov r3, r3, lsr #8mov r3, r3, asl #16mov r3, r3, lsr #16and r2, r3, #255ldrh r3, [fp, #-6]and r3, r3, #255ldr r0, .L3+4mov r1, r2mov r2, r3bl printf

arm-none-eabi-gcc, -Os, 這個清爽多了, 前者3條指令, 后者4條指令.

bl scanfldrb r1, [sp, #7] @ zero_extendqisi2ldrb r2, [sp, #6] @ zero_extendqisi2 ; 錯開1字節mov r0, r4 ; .L3+4被提前放進r4了bl printfldrh r1, [sp, #6]mov r0, r4mov r1, r1, lsr #8 ; 移位ldrb r2, [sp, #6] @ zero_extendqisi2bl printf

avr-gcc呢, 太長就不貼了. 不過-Os時反倒是移位方式的指令更少.

總之以上四種情況都是前者好些. 不過實際運行時也不一定, 沒準后者更快呢?

----------------2020.2.22補充-------------------

還有一個重要的區別:前者可以作為左值,后者不行。

如下程序:

#include <stdio.h>#define hi8(x) ((( struct { unsigned char l; unsigned char h; } *)(&x))->h) #define lo8(x) ((( struct { unsigned char l; unsigned char h; } *)(&x))->l) int main(void) {unsigned short x = 0x1234;hi8(x)--;lo8(x)++;printf("%xn", x);return 0; }

運行,結果是1135。

總結

以上是生活随笔為你收集整理的lcd取模如何取16位_两种方式实现取16位变量的高低8位, 不严谨对比的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。