一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

使用匯編知識(shí)排查疑難問(wèn)題的方法

RTThread物聯(lián)網(wǎng)操作系統(tǒng) ? 來(lái)源:RTThread物聯(lián)網(wǎng)操作系統(tǒng) ? 作者:recan ? 2022-07-27 10:31 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1 前言


在我的上一篇文章中,有講到掌握匯編知識(shí)的重要性,關(guān)鍵時(shí)刻可能還會(huì)拯救你于泥潭之中。

那么,本篇文章,我將再介紹一個(gè)使用匯編知識(shí)排查疑難問(wèn)題的方法,希望對(duì)大家有所幫助。

2 問(wèn)題描述


問(wèn)題是這樣的,前一段時(shí)間我們項(xiàng)目組在進(jìn)行一項(xiàng)自測(cè)試中,偶然發(fā)現(xiàn)我們的代碼好像掛了一樣:現(xiàn)象就是命令行輸入不了,但是沒(méi)有看到復(fù)位信息輸出。

當(dāng)時(shí),我們一個(gè)小伙伴說(shuō):“好像我們的系統(tǒng)掛了?”當(dāng)我了解到這個(gè)現(xiàn)象之后,根據(jù)我之前的排查經(jīng)驗(yàn),我當(dāng)即得出了一個(gè)結(jié)論:“可能是我們的代碼跑進(jìn)死循環(huán)了,好好檢查下”!

于是,我們開(kāi)始debug代碼,加了一些必要的調(diào)試信息,最終發(fā)現(xiàn)有一個(gè)計(jì)算校驗(yàn)的函數(shù),調(diào)進(jìn)去了但是沒(méi)有退出來(lái),而這個(gè)校驗(yàn)的函數(shù)非常之簡(jiǎn)單,它就長(zhǎng)這樣:

uint16_t checksum(uint8_t *data, uint8_t len){    uint8_t i;    uint16_t sum = 0, res;    for (i = 0; i < len; i++) {        sum += data[i];    }    res = sum ;    return res;}

我想當(dāng)你看到這段函數(shù)時(shí),肯定也是:“臥槽,這TM不就是算累加校驗(yàn)和嗎?怎么可能會(huì)死循環(huán)?”

沒(méi)錯(cuò),當(dāng)時(shí)我們的爭(zhēng)論的場(chǎng)景也的確如此!

3 簡(jiǎn)單分析


這個(gè)checksum函數(shù)真的是非常簡(jiǎn)單,入?yún)⒑?jiǎn)單、實(shí)現(xiàn)也簡(jiǎn)單、返回值也簡(jiǎn)單,根本不存在難點(diǎn)。

一步步來(lái)分析:

既然代碼沒(méi)有崩潰,證明data指針肯定非NULL的,不會(huì)有問(wèn)題;

倒是這個(gè)len有些可疑,len的類型是uint8_t無(wú)符號(hào)的,它的范圍是0-255;但是如果外面?zhèn)魅氲氖?1呢?

如果傳入-1,強(qiáng)制轉(zhuǎn)換為uint8_t,其值也是255,那么下面的for循環(huán),依然只會(huì)跑256次,它必須得退出呀?

有沒(méi)有可能for循環(huán)的過(guò)程中,棧的值被修改了,然后i的值和len的值都變了,進(jìn)而for的次數(shù)改變了?

于是我們開(kāi)始打印i和len的值,發(fā)現(xiàn)他們兩個(gè)的值,都是正常變化的,并不是剛剛想的那樣。

這就很奇怪了?。。?/span>

如果說(shuō)這個(gè)for循環(huán)要“無(wú)限”循環(huán)下去,造成“死循環(huán)”,必須滿足的條件是len很大很大,但是len不是uint8_t類型嘛?最大也就255呀?

printf大法再來(lái)一遍:結(jié)果出乎我們的意料,請(qǐng)看:

6ab63322-0ce3-11ed-ba43-dac502259ad0.png

log輸出:

[12-21 1938]checksum 128 len: 4294967295[12-21 1938]0 4294967295[12-21 1938]1 4294967295[12-21 1938]2 4294967295[12-21 1938]3 4294967295[12-21 1938]4 4294967295[12-21 1938]5 4294967295[12-21 1938]6 4294967295[12-21 1938]7 4294967295[12-21 1938]8 4294967295[12-21 1938]9 4294967295[12-21 1938]10 4294967295    。。。省略很多[12-21 1938]250 4294967295[12-21 1938]251 4294967295[12-21 1938]252 4294967295[12-21 1938]253 4294967295[12-21 1938]254 4294967295[12-21 1938]255 4294967295[12-21 1938]256 4294967295[12-21 1938]257 4294967295[12-21 1938]258 4294967295[12-21 1938]259 4294967295[12-21 1938]260 4294967295

。。。還在不停的打印

看到這里似乎有點(diǎn)眉目了?len的值為4294967295?

這個(gè)值不是0xFFFFFFFF嗎?

我們?cè)偈褂?d打印了一下len,發(fā)現(xiàn)值為-1。

回過(guò)頭來(lái)看下checksum的調(diào)用之處:

uint16_t res = checksum(&data[0], len - 1);

看似真相了,當(dāng)len為0的時(shí)候,傳入的值不就是-1嗎?

好像是這么回事,但是-1進(jìn)去,它是uint8_t的呀,頂多就是255???怎么變成了4294967295? 到底是誰(shuí)干的???

同時(shí)也發(fā)現(xiàn)關(guān)鍵問(wèn)題了,這里并不是真正意義的“死循環(huán)”,而是for循環(huán)執(zhí)行太久了,導(dǎo)致長(zhǎng)時(shí)間無(wú)法結(jié)束,因?yàn)槲覀兊闹黝l才160MHZ,CPU就是猛跑,從1加到0xFFFFFFFF,也需要好長(zhǎng)一段時(shí)間呢!

4 場(chǎng)景再現(xiàn)


為了充分說(shuō)明這個(gè)問(wèn)題,我盡可能地還原下當(dāng)時(shí)我們的代碼場(chǎng)景:

/*一個(gè)結(jié)構(gòu)體定義數(shù)據(jù)不要急于吐槽它的定義,這代碼是開(kāi)源的,冤有頭。。。還有不要懷疑是字節(jié)對(duì)齊不對(duì)齊的問(wèn)題,曾經(jīng)我也懷疑過(guò),最后知道真相的時(shí)候,我被打臉了!*/typedef struct _data_t {    /* result, final result */    uint8_t len;    uint8_t flag;    uint8_t passwd_len;     uint8_t *passwd;     uint8_t ssid_len;     uint8_t *ssid;     uint8_t token_len;     uint8_t *token;     uint8_t bssid_type_len;     uint8_t *bssid;     uint8_t ssid_is_gbk;    uint8_t ssid_auto_complete_disable;    uint8_t data[127];    uint8_t checksum;} data_t;

/* 1.c 調(diào)用checksum的C文件 *//* 定義全局的數(shù)據(jù) */static data_t g_data;/* 設(shè)置全局的數(shù)據(jù) */void set_global_data(void){    g_data.len = 0;}void handle_global_data(void){      uint16_t res = checksum(&g_data.data[0], g_data.len - 0);  //sometimes no return form checksum}void test_func_entry(void){    set_global_data();    handle_global_data();}
/* 2.c 定義checksum函數(shù)的工具類 */uint16_t checksum(uint8_t *data, uint8_t len){    uint8_t i;    uint16_t sum = 0, res;    for (i = 0; i < len; i++) {        sum += data[i];    }    res = sum ;    return res;}

在我的第一次認(rèn)知里,還是len=-1=255的情況,由于g_data.data只有127字節(jié),但它最后是可以訪問(wèn)到255下標(biāo)的,其實(shí)這本身就有數(shù)據(jù)非法訪問(wèn)的問(wèn)題;但是經(jīng)過(guò)仔細(xì)論證,得出的結(jié)論是,這并不會(huì)導(dǎo)致死循環(huán),或者說(shuō)并不會(huì)改變len的值;因?yàn)閏hecksum里面知識(shí)讀取data指針的值,并沒(méi)改變它的值,即便越界了,頂多訪問(wèn)了別人,并不會(huì)出啥異常(至少在我們的處理器平臺(tái)是這樣)。

這個(gè)問(wèn)題對(duì)我們來(lái)說(shuō),真的是百思不得其解,為了規(guī)避掉這個(gè)問(wèn)題,我們?cè)谡{(diào)用checksum的時(shí)候做了判斷,但len為0的時(shí)候直接不調(diào)用,也就繞過(guò)了這個(gè)問(wèn)題。

但是作為一個(gè)深挖底層邏輯的攻城獅來(lái)說(shuō),我們不應(yīng)該放過(guò)這樣的細(xì)節(jié),或許還有什么我們未發(fā)現(xiàn)的潛在風(fēng)險(xiǎn)呢?

這個(gè)問(wèn)題一直困擾著我,時(shí)不時(shí)有空的時(shí)候,我就會(huì)想想,到底還有什么情況還會(huì)導(dǎo)致這個(gè)現(xiàn)象?

5 柳暗花明


偶然有一天,我正瀏覽到一篇關(guān)于編譯器做代碼優(yōu)化的文章,它是在知乎上發(fā)出來(lái)的,我看到其中一個(gè)重要線索:

6adccf5a-0ce3-11ed-ba43-dac502259ad0.png

突然我腦子里,閃過(guò)一個(gè)疑問(wèn):“會(huì)不會(huì)那段for循環(huán)的checksum函數(shù),正是因?yàn)檎{(diào)用方?jīng)]有申明checksum函數(shù),也就是說(shuō)沒(méi)有include對(duì)應(yīng)的頭文件導(dǎo)致編譯器做了默認(rèn)處理呢?”?

我們都知道,在使用gcc編譯器編譯C代碼時(shí),如果一個(gè)函數(shù)未申明就調(diào)用,是會(huì)報(bào)一個(gè)警告的:“warning: implicit declaration of function ‘checksum’ [-Wimplicit-function-declaration]”!

同時(shí),尤其編譯器不知道被調(diào)用函數(shù)的原型,那么它只能依靠你的調(diào)用代碼結(jié)合一些默認(rèn)值做假設(shè):

比如我們的調(diào)用代碼是:

uint16_t res = checksum(&g_data.data[0], g_data.len - 0);

這里,我猜測(cè)編譯器的行為就是,你有一個(gè)叫checksum的函數(shù),但我找不到它的原型,那么我就按“返回值是uint16_t類型,第一個(gè)參數(shù)是int型,第二個(gè)參數(shù)也是int型”來(lái)吧!

為何,gcc默認(rèn)參數(shù)列表都是int類型?這是我的假想猜測(cè),下面我們?cè)僬撟C,究竟是不是這樣?

有了這個(gè)假設(shè)之后,我們回到ARM匯編在函數(shù)調(diào)用時(shí)的參數(shù),這時(shí)R0應(yīng)該等于&g_data.data[0],R1應(yīng)該等于-1。

由于R0/R1都是32位的寄存器,在存儲(chǔ)數(shù)據(jù)的時(shí)候,無(wú)所謂有符號(hào)和無(wú)符號(hào)一說(shuō),且本問(wèn)題R0沒(méi)有出現(xiàn)問(wèn)題,我們僅討論R1。

這個(gè)時(shí)候R1的寄存器值,應(yīng)該是“-1 = 0xFFFFFFFF”,這個(gè)假設(shè)很關(guān)鍵,如果分析地很順利,那么這個(gè)for循環(huán)不停地循環(huán)下去,才可以有理論進(jìn)行下去。

6 找到證據(jù)


既然上面我們發(fā)現(xiàn)了端倪,那么我們應(yīng)該進(jìn)一步找到相關(guān)的證據(jù),證明我們的想法;同時(shí),如果這個(gè)問(wèn)題根源在于include頭文件,那么當(dāng)我們添加了頭文件之后,這個(gè)問(wèn)題應(yīng)該不會(huì)再?gòu)?fù)現(xiàn)。我們來(lái)看下,究竟是不是這樣?

6.1 究竟是不是警告

由于我們的代碼實(shí)在太多警告了,就屬于那種 0 error N warnings 那種,屬于你需要找一個(gè)警告往往好費(fèi)好大勁!

6b15b914-0ce3-11ed-ba43-dac502259ad0.png

經(jīng)過(guò)好一番檢索,果不其然,還真的報(bào)警告了,的確是“warning: implicit declaration of function ‘checksum’ [-Wimplicit-function-declaration]”!

6.2 盤根問(wèn)底

看編譯器的行為,我們肯定是要看其對(duì)應(yīng)的匯編文件,這里有兩個(gè)地方需要看,一個(gè)是checksum函數(shù)的匯編,還有一個(gè)調(diào)用checksum函數(shù)附近的匯編。

我們一起看看:

/* checksum 函數(shù)的匯編代碼 */    .section    .text.checksum,"ax",%progbits    .align    1    .global    checksum    .code    16    .thumb_func    .type    checksum, %functionchecksum:.LFB4:    .loc 1 125 0    .cfi_startproc    @ args = 0, pretend = 0, frame = 0    @ frame_needed = 0, uses_anonymous_args = 0.LVL27:    push    {r4, r5, r6, lr}    .cfi_def_cfa_offset 16    .cfi_offset 4, -16    .cfi_offset 5, -12    .cfi_offset 6, -8    .cfi_offset 14, -4    .loc 1 125 0    movs    r4, r0    movs    r5, r1  // r1 -> r5 ,即 len的值存在r5中    .loc 1 129 0    movs    r2, r1    ldr    r0, .L29.LVL28:    bl    printf  //打印len的值.LVL29:    movs    r3, r4    .loc 1 127 0    movs    r0, #0    adds    r5, r4, r5.LVL30:.L26:    .loc 1 130 0 discriminator 1    cmp    r3, r5  //for循環(huán)里面的關(guān)鍵判斷,即 i < len    beq    .L28 // 退出for循環(huán)    .loc 1 131 0 discriminator 3 //下面就是for循環(huán)的循環(huán)執(zhí)行體    ldrb    r2, [r3]    adds    r3, r3, #1.LVL31:    adds    r0, r0, r2.LVL32:    lsls    r0, r0, #16    lsrs    r0, r0, #16.LVL33:    b    .L26.LVL34:.L28:    .loc 1 136 0    @ sp needed.LVL35:    pop    {r4, r5, r6, pc}.L30:    .align    2.L29:    .word    .LC12    .cfi_endproc.LFE4:    .size    checksum, .-checksum

由它的匯編代碼可知,for循環(huán)執(zhí)行多少次,關(guān)鍵在于r5寄存器的值,也就是len的值。

注意在匯編代碼這里,是看不到r5是uint8_t還是uint32_t的,它僅僅是一個(gè)32位的寄存器。

    .section    .text.verify_checksum,"ax",%progbits    .align    1    .global    verify_checksum    .code    16    .thumb_func    .type    verify_checksum, %functionverify_checksum:.LFB5:    .loc 1 81 0    .cfi_startproc    @ args = 0, pretend = 0, frame = 0    @ frame_needed = 0, uses_anonymous_args = 0.LVL17:    push    {r4, lr}    .cfi_def_cfa_offset 8    .cfi_offset 4, -8    .cfi_offset 14, -4    .loc 1 83 0    ldr    r4, .L20    .loc 1 91 0    @ sp needed    .loc 1 83 0    movs    r0, r4   //r0存儲(chǔ)結(jié)構(gòu)體g_data的地址    ldrb    r1, [r4] //將g_data的第一個(gè)字節(jié),即g_data.len賦值為r1    adds    r0, r0, #34 //r0的地址偏移34個(gè)字節(jié),即偏移到g_data.data的位置;    subs    r1, r1, #1  //關(guān)鍵的一步:r1 = r1 - 1 由于我們復(fù)現(xiàn)問(wèn)題的時(shí)候,g_data.len是為0的,所以此時(shí)r1的值就是0xFFFFFFFF    bl    checksum    //調(diào)用checksum函數(shù),第1-2個(gè)入?yún)ⅲ謩e是r0和r1.LVL18:    .loc 1 84 0    adds    r4, r4, #160    .loc 1 89 0    ldrb    r3, [r4]    lsls    r0, r0, #24.LVL19:    lsrs    r0, r0, #24    subs    r0, r0, r3    .loc 1 91 0    pop    {r4, pc}.L21:    .align    2.L20:    .word    .LANCHOR4    .cfi_endproc.LFE5:    .size    verify_checksum, .-verify_checksum

了解匯編知識(shí)的,看到上面的匯編代碼,結(jié)合checksum函數(shù)的匯編代碼,就應(yīng)該明白,我前面的假設(shè)成立了,但len傳入到checksum函數(shù)時(shí),它的值真的是0xFFFFFFFF,而使用%u打印出來(lái),就是4294967295。

到此,罪魁禍?zhǔn)灼鋵?shí)已經(jīng)找到了,與其說(shuō)是編譯器的無(wú)故優(yōu)化,倒不如說(shuō)是程序猿寫代碼不嚴(yán)謹(jǐn),沒(méi)有正確處理掉這個(gè)編譯警告。

6.3 解除風(fēng)險(xiǎn)

既然找到了問(wèn)題根源,那么我們嘗試下解除這個(gè)風(fēng)險(xiǎn)。

方法其實(shí)也很簡(jiǎn)單,直接需要在調(diào)用checksum函數(shù)的1.c中,include一下checksum函數(shù)所在的頭文件即可。

添加之后,我們看下發(fā)生的變化,很顯然,checksum函數(shù)的匯編代碼肯定是沒(méi)有任何不變的,應(yīng)該它壓根沒(méi)有改;

而調(diào)用checksum的匯編就發(fā)生了些許的變化,同時(shí)編譯輸出的地方,那個(gè)編譯警告也都消失了。

* 添加頭文件之后的匯編代碼 */        .section    .text.verify_checksum,"ax",%progbits    .align    1    .global    verify_checksum    .code    16    .thumb_func    .type    verify_checksum, %functionverify_checksum:.LFB5:    .loc 1 81 0    .cfi_startproc    @ args = 0, pretend = 0, frame = 0    @ frame_needed = 0, uses_anonymous_args = 0.LVL17:    push    {r4, lr}    .cfi_def_cfa_offset 8    .cfi_offset 4, -8    .cfi_offset 14, -4    .loc 1 83 0    ldr    r4, .L20    .loc 1 91 0    @ sp needed    .loc 1 83 0    movs    r0, r4    ldrb    r1, [r4]    adds    r0, r0, #34    subs    r1, r1, #1   //r1寄存器的一樣的操作 r1 = r1 - 1    lsls    r1, r1, #24  //關(guān)鍵改變!?。1 = r1 * (2的24次冪),也就是算術(shù)左移24位    lsrs    r1, r1, #24  //關(guān)鍵改變?。?!r1 = r1 / (2的24次冪),也就是算術(shù)右移24位    bl    checksum.LVL18:    .loc 1 84 0    adds    r4, r4, #160    .loc 1 89 0    ldrb    r3, [r4]    lsls    r0, r0, #24.LVL19:    lsrs    r0, r0, #24    subs    r0, r0, r3    .loc 1 91 0    pop    {r4, pc}.L21:    .align    2.L20:    .word    .LANCHOR4    .cfi_endproc.LFE5:    .size    verify_checksum, .-verify_checksum

為了好對(duì)比,我直接使用對(duì)比工具貼圖上來(lái)看下:

6b30f22e-0ce3-11ed-ba43-dac502259ad0.png

查了下多出來(lái)的這兩條指令:lsls和lsrs,參考這里。

一個(gè)是算術(shù)左移24位,一個(gè)是算術(shù)右移24位,倒來(lái)倒去,無(wú)非就是把高24位給情況,這樣-1的值傳入checksum的時(shí)候,就只有0x000000FF了,而不是0xFFFFFFFF。

這樣就把uint8_t len拉回正常的邏輯了,自然也就不會(huì)出現(xiàn)之前的for循環(huán)一直退不出來(lái)了。

7 擴(kuò)展延伸


上面我提及的場(chǎng)景對(duì)應(yīng)的是ARM平臺(tái)的,由于我們的代碼是跨平臺(tái)的,支持RISC-V架構(gòu),X86架構(gòu)等等。

7.1 RISC-V架構(gòu)

所以我們來(lái)對(duì)比看下RISC-V架構(gòu)下的情況:

這么看,RISC-V的處理也是夠粗暴的,一個(gè)addi指令,把高24位去掉就完事了?。?!

7.2 80x86架構(gòu)

我push了一個(gè)簡(jiǎn)易的工程代碼到github,以便于重現(xiàn)此問(wèn)題,感興趣的可以看這里。

很遺憾的是,在80x86上竟然沒(méi)有復(fù)現(xiàn)此問(wèn)題。

代碼的核心差別就是是否include 2.h:

6b4c960a-0ce3-11ed-ba43-dac502259ad0.png

匯編代碼確實(shí)有差異:

6b7bc164-0ce3-11ed-ba43-dac502259ad0.png

但是跑出來(lái)的效果確實(shí)一樣的:

6ba49e40-0ce3-11ed-ba43-dac502259ad0.png

總結(jié)下沒(méi)有復(fù)現(xiàn)問(wèn)題的原因,可能是:

編譯選項(xiàng)沒(méi)有使用正確?

80x86編譯器更懂事?更能知道如何合理編譯代碼?

還有未知的編譯特性未了解到?

7.3 其他架構(gòu)

感興趣的可以在其他平臺(tái)上驗(yàn)證下,是否有類似的問(wèn)題,歡迎討論。

8 經(jīng)驗(yàn)總結(jié)


請(qǐng)?zhí)嵘愕拇a編譯嚴(yán)謹(jǐn)性,如果是gcc編譯器,-Wall -Werror -Os是最低要求;

談優(yōu)化代碼前,請(qǐng)close掉你的代碼編譯異常,先達(dá)到 0 error 0 warning 再說(shuō);

請(qǐng)重視warning: implicit declaration of function這個(gè)編譯警告;

如果使用gcc編譯器,不提示任何編譯警告和錯(cuò)誤,并不代表編譯器沒(méi)有告訴你,也許是你使用-w選項(xiàng)編譯了輸出,你僅僅是在自欺欺人而已;

老老實(shí)實(shí)在調(diào)用函數(shù)前申明你的函數(shù),或者包含其對(duì)應(yīng)的頭文件,有時(shí)候編譯器的默認(rèn)行文不見(jiàn)得就可靠;

代碼細(xì)節(jié)很重要,真的是細(xì)節(jié)決定成??;

不放過(guò)一絲可能性,作為一個(gè)攻城獅,這點(diǎn)專研精神需要時(shí)刻掛在心里;

大膽假設(shè),小心求證,亙古不變的方法論。

審核編輯:湯梓紅


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 匯編
    +關(guān)注

    關(guān)注

    2

    文章

    214

    瀏覽量

    26537
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4899

    瀏覽量

    70595

原文標(biāo)題:【匯編實(shí)戰(zhàn)開(kāi)發(fā)筆記】從匯編代碼中找出一段普通的for循環(huán)變成“死循環(huán)”的根本原因

文章出處:【微信號(hào):RTThread,微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    使用匯編知識(shí)排查疑難問(wèn)題方法

    那么,本篇文章,我將再介紹一個(gè)使用匯編知識(shí)排查疑難問(wèn)題方法,希望對(duì)大家有所幫助。
    發(fā)表于 07-27 10:31 ?864次閱讀

    如何使用內(nèi)聯(lián)函數(shù)法調(diào)用匯編函數(shù)?

    從C/C++中調(diào)用匯編代碼中的函數(shù)使用內(nèi)聯(lián)函數(shù)法調(diào)用匯編函數(shù)從C/C++中調(diào)用匯編代碼中的變量或者常量
    發(fā)表于 04-02 06:57

    為什么要用匯編語(yǔ)言寫程序

    我們這學(xué)期開(kāi)了單片機(jī)的課,不知道為什么我們要用匯編語(yǔ)言寫程序,感覺(jué)匯編程序真的挺難寫的,所以把實(shí)驗(yàn)記錄下來(lái)把。如果沒(méi)有學(xué)過(guò)匯編的小伙伴建議先去熟悉一下簡(jiǎn)單的匯編指令,之前簡(jiǎn)單的實(shí)驗(yàn)我就
    發(fā)表于 11-10 08:32

    飛控中的疑難問(wèn)題分享

    飛控中的疑難問(wèn)題(一)最近在用無(wú)名創(chuàng)新的飛控來(lái)進(jìn)行二次開(kāi)發(fā)。遇到了一些較為奇怪的問(wèn)題,部分已經(jīng)解決,但還是有一部分問(wèn)題較為復(fù)雜,特此和大家分享一下。希望大家可以分享、互相幫助解決遇到的問(wèn)題。(一
    發(fā)表于 01-13 07:31

    如何有效地排查內(nèi)存泄露的疑難問(wèn)題

    。通過(guò)本文的閱讀,你將可以了解到以下幾部分核心內(nèi)容:一種業(yè)內(nèi)常見(jiàn)常用的【內(nèi)存管理】方案介紹;判斷【內(nèi)存泄露】的簡(jiǎn)單方法;如何通過(guò)鉤子操作替換原生的內(nèi)存操作接口;如果通過(guò)編譯器的一些特殊功能,縮減排查方案
    發(fā)表于 09-01 14:47

    如何在C程序中使用匯編

    怎樣在C程序中使用匯編,如何在C程序中使用匯編:方法一:在每個(gè)匯編語(yǔ)句前加asm即可。如:void reset_data(void) { asm mov r0,#0dfh asm
    發(fā)表于 09-23 23:43 ?55次下載

    視頻會(huì)議系統(tǒng)中常見(jiàn)的疑難問(wèn)題解答

    視頻會(huì)議系統(tǒng)中常見(jiàn)的疑難問(wèn)題解答 1.我可以同時(shí)使用兩支相同頻率的話筒嗎   不能同時(shí)使用。無(wú)線傳輸不能在空中“相混合”,即
    發(fā)表于 02-21 09:08 ?1152次閱讀

    電腦入門與提高疑難排解大全

    《電腦入門與提高疑難排解大全》主要針對(duì)電腦用戶在使用電腦的過(guò)程中經(jīng)常遇到的各種疑難問(wèn)題,從實(shí)用、便捷的角度出發(fā),講述具體的應(yīng)對(duì)方法及處理技巧。內(nèi)容主要包括操作系統(tǒng)
    發(fā)表于 01-17 17:12 ?81次下載

    模擬電子疑難問(wèn)題解惑系列(三):成為熟練的電子工程師

    前面我們?yōu)榇蠹铱偨Y(jié)了模擬電子學(xué)習(xí)中經(jīng)常遇到的系列疑難問(wèn)題的總結(jié),今天為大家?guī)?lái)了模擬電子問(wèn)題解惑系列三,供大家學(xué)習(xí)
    發(fā)表于 11-29 18:03 ?3507次閱讀

    模擬電子疑難問(wèn)題解惑系列(四):濾波器、振蕩器

    電子發(fā)燒友網(wǎng)訊:前面我們?yōu)榇蠹規(guī)?lái)了模擬電子學(xué)習(xí)中經(jīng)常遇到的系列疑難問(wèn)題的總結(jié),今天為大家?guī)?lái)了模擬電子問(wèn)題解惑系列四,供大家學(xué)習(xí)。
    發(fā)表于 12-17 11:33 ?5275次閱讀

    關(guān)于高速AD/DAC測(cè)量及設(shè)計(jì)中82個(gè)疑難問(wèn)題的解答

    本文首先介紹了ADC的參數(shù)、測(cè)試方案及對(duì)測(cè)試結(jié)果進(jìn)行了分析,其次介紹了DAC參數(shù)、測(cè)試方案及結(jié)果分析,其次對(duì)AD/DA轉(zhuǎn)換設(shè)計(jì)中82個(gè)疑難問(wèn)題解答。
    發(fā)表于 04-20 16:24 ?1.6w次閱讀
    關(guān)于高速AD/DAC測(cè)量及設(shè)計(jì)中82個(gè)<b class='flag-5'>疑難問(wèn)題</b>的解答

    51單片機(jī)C語(yǔ)言調(diào)用匯編子程序的簡(jiǎn)便方法程序和工程文件免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是51單片機(jī)C語(yǔ)言調(diào)用匯編子程序的簡(jiǎn)便方法程序和工程文件免費(fèi)下載。
    發(fā)表于 10-10 08:00 ?3次下載
    51單片機(jī)C語(yǔ)言調(diào)<b class='flag-5'>用匯編</b>子程序的簡(jiǎn)便<b class='flag-5'>方法</b>程序和工程文件免費(fèi)下載

    單片機(jī)使用匯編開(kāi)發(fā)的簡(jiǎn)單介紹

    匯編語(yǔ)言(Assembly Language)是一種用于電子計(jì)算機(jī)、微處理器、微控制器或其它可編程器件的低級(jí)語(yǔ)言。在單片機(jī)出現(xiàn)之初,由于性能限制,都是使用匯編進(jìn)行開(kāi)發(fā)。隨著技術(shù)的發(fā)展,制程工藝的提升
    發(fā)表于 11-13 19:06 ?13次下載
    單片機(jī)使<b class='flag-5'>用匯編</b>開(kāi)發(fā)的簡(jiǎn)單介紹

    在C中使用匯編程序的原因是?

    當(dāng)使用匯編語(yǔ)言時(shí),我們經(jīng)常將它使用在代碼中的一小部分上。有兩種使用匯編語(yǔ)言的方法:在C中調(diào)用匯編子程序或內(nèi)嵌匯編。內(nèi)嵌
    的頭像 發(fā)表于 04-04 15:00 ?1308次閱讀
    在C中使<b class='flag-5'>用匯編</b>程序的原因是?

    21個(gè)最常見(jiàn)晶振應(yīng)用疑難問(wèn)題及解答

    21個(gè)最常見(jiàn)晶振應(yīng)用疑難問(wèn)題及解答
    的頭像 發(fā)表于 06-10 16:56 ?2063次閱讀