| Profilo di jiyu人生路漫漫,快乐先行FotoBlogElenchi | Guida |
人生路漫漫,快乐先行28 maggio 迁移博客,欢迎大家访问 http://jiyu.wordpress.com.cn/博客迁移,欢迎大家访问 http://jiyu.wordpress.com.cn/ 新的blog关注python, Google App Engine, 奇思异想, webapplication, mobileapplication, javascript等 14 maggio 嵌入式程序员应知道的基本问题-C语言(zz)来源:21ICbbs 作者:lhf C语言测试:想成为嵌入式程序员应知道的0x10个基本问题 其中少量灰色的文字是我添加的,表达一些我的看法,很不成熟,希望朋友们指正。 C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法。这些年,我既参加也组织了许多这种测试,在这过程中我意识到这些测试能为带面试者和被面试者提供许多有用信息,此外,撇开面试的压力不谈,这种测试也是相当有趣的。
1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
这个测试是为下面的目的而设的: least = MIN(*p++, b);
while(1) do{ ... } while (1) 一些程序员更喜欢如下方案: for(;;)
这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。 Loop:
数据声明(Data declarations) 5. 用变量a给出下面的定义 答案是: typedef int (*PFUNCTION)(int) PFUNCTION pfun; typedef int (*PFUNCTION)(int) PFUNCTION pfun[10];
7.关键字const有什么含意? const int a; /******/
8. 关键字volatile有什么含意?并给出三个不同的例子。 下面是答案:
long square(volatile int *ptr) 位操作(Bit manipulation) 9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。
void set_bit3(void) { 一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。
10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。 int *ptr; A more obscure approach is: *(int * const)(0x67a9) = 0xaa55; 即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。 中断(Interrupts) 11. 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_area (double radius) 这个函数有太多的错误了,以至让人不知从何说起了:
12 . 下面的代码输出是什么,为什么? void foo(void) 13. 评价下面的代码片断: unsigned int zero = 0; 对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下: unsigned int compzero = ~0; 这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。 动态内存分配(Dynamic memory allocation) char *ptr; 所以在这个时候,一定要使用pc-lint来检察代码规范性,起码pc-lint能检查出if-else语句格式不对,要求开发人员对格式进行修改,那样的话,看起来就方便多了。 这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是“Got a valid pointer”。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。
#define dPS struct s * 以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么? dPS p1,p2; 第一个扩展为 struct s * p1, p2; . 晦涩的语法 16 . C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么? int a = 5, b = 7, c; 这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成: c = a++ + b; 因此, 这段代码持行后a = 6, b = 7, c = 12。 让你明白什么是ERP(zz)ERP(Enterprise Resource Planning)企业资源计划系统,是指建立在信息技术基础上,以系统化的管理思想,为企业决策层及员工提供决策运行手段的管理平台。 一天中午,丈夫在外给家里打电话:"亲爱的老婆,晚上我想带几个同事回家吃饭可以吗?"(订货意向) 妻子:"当然可以,来几个人,几点来,想吃什么菜?" 丈夫:"6个人,我们7点左右回来,准备些酒、烤鸭、番茄炒蛋、凉菜、蛋花汤......。你看可以吗?"(商务沟通) 妻子:"没问题,我会准备好的。"(订单确认) 妻子记录下需要做的菜单(MPS计划),具体要准备的东西:鸭、酒、番茄、鸡蛋、调料......(BOM物料清单),发现需要:1只鸭蛋,5瓶酒,4个鸡蛋......(BOM展开),炒蛋需要6个鸡蛋,蛋花汤需要4个鸡蛋(共用物料)。 打开冰箱一看(库房),只剩下2个鸡蛋(缺料)。 来到自由市场,妻子:"请问鸡蛋怎么卖?"(采购询价) 小贩:"1个1元,半打5元,1打9.5元。" 妻子:"我只需要8个,但这次买1打。"(经济批量采购) 妻子:"这有一个坏的,换一个。"(验收、退料、换料) 回到家中,准备洗采、切菜、炒菜......(工艺线路),厨房中有燃气灶、微波炉、电饭煲......(工作中心)。妻子发现拨鸭毛最费时间(瓶颈工序,关键工艺路线),用微波炉自己做烤鸭可能来不及(产能不足),于是阅览室在楼下的餐厅里买现成的(产品委外)。 下午4点,电话铃又响:"妈妈,晚上几个同学想来家里吃饭,你帮忙准备一下。"(紧急订单) "好的,你们想吃什么,爸爸晚上也有客人,你愿意和他们一起吃吗?" "菜你看着办吧,但一定要有番茄炒鸡蛋,我们不和大人一起吃,6:30左右回来。"(不能并单处理) "好的,肯定让你们满意。"(订单确定) 鸡蛋又不购了,打电话叫小贬送来。(紧急采购) 6:30,一切准备就绪,可烤鸭还没送来,急忙打电话询问:"我是李太,怎么订的烤鸭还不送来?"(采购委外单跟催) "不好意思,送货的人已经走了,可能是堵车吧,马上就会到的。" 门铃响了。"李太太,这是您要的烤鸭。请在单上签一个字。"(验收、入库、转应付账款) 6:45,女儿的电话:"妈妈,我想现在带几个朋友回家吃饭可以吗?"(呵呵,又是紧急订购意向,要求现货) "不行呀,女儿,今天妈已经需要准备两桌饭了,时间实在是来不及,真的非常抱歉,下次早点说,一定给你们准备好。"(哈哈,这就是ERP的使用局限,要有稳定的外部环境,要有一个起码的提前期) 送走了所有客人,疲惫的妻子坐在沙发上对丈夫说:"亲 爱的,现在咱们家请客的频率非常高,应该要买些厨房用品了(设备采购),最好能再雇个小保姆(连人力资源系统也有接口了)。 丈夫:"家里你做主,需要什么你就去办吧。"(通过审核) 妻子:"还有,最近家里花销太大,用你的私房钱来补贴一下,好吗?"(最后就是应收货款的催要) 现在还有人不理解ERP吗?记住,每一个合格的家庭都是生产厂长的有力竞争者! 07 maggio 关于汇编语言内存寻址方式浅析(转)指令操作数的寻址方式
一、与数据有关,寻找参加操作的数据(8种---->7种基本方式+字符串寻址) ★涉及的一些概念 DISP/16位:AX(累加器),BX(基侄寄存器),CX(计数器),DX(数据与地址寄存器),SP(堆栈指针),BP(基址指针),SI(源变址器),DI(目的变址器) DISP/8位:AH(高8位),AL(低8位),BH,BL,CH,CL.DH,DL IP指令指针,存放代码段中的偏移地址;EA偏移地址,段内相对地址,有效地址 CS代码段,SS堆栈段,DS数据段,ES附加段 堆栈:方便事项程序要求保留和恢复有关信息的特殊存储部件,是一种数据结构。 pws(状态):CF(进位),PF(奇偶),SF(符号),OF(溢出),ZF(零),DF(方向),IF(中断),TF(跟踪) PA:20位物理地址 ;MOV传送 1、立即寻址 用来表示常数 MOV AX,1946H;1946H(立即数)-->AX 2、寄存器寻址 MOV AX,CX ;cx-->ax 3、直接寻址 MOV BX,[1000H] ;[1000H]→EA,操作数默认DS MOV AX,ES:VAR ;越段前缀 4、寄存器间接寻址 EA=BX∨SI∨DI∨BP;∨表示或者 a、PA=DS×16+{BX∨SI∨DI} b、PA=SS×16+BP c、PA=越段寄存器×16+{BX∨SI∨DI∨BP} 5、寄存器相对寻址 直接变址寻址 ┍BX┑ EA=├SI┥+{DISP} ├DI┥ ┕BP┚ mov ax,count[si] ;ea=count+si,(ea)→ax,约定为DS mov al,es:string[bp] ;越段前缀 6、基址变址寻址 使用数组和表格 EA={BX∨BP}+{SI∨DI} pA=DS×16+BX+{SI∨DI} pA=SS×16+BP+{SI∨DI} mov cx,es:[bx][di] mov ax,[bx][si] ;ea=bx+si,ea→ax 7、相对基址变址寻址 EA={BX∨BP}+{SI∨DI}+{DISP} mov ax,array[bx][si] ;ea=array+bx+si,ea→ax 8、字符串寻址 movsb ;([si])=>([di]),si+1=>si,di+1=>di ;源=>目,可理解为mov [di],[si] 我对寻址的一些分析看看对大家对他的理解有没有帮助。 物理地址(PA)=段地址+偏移地址(EA) =段寄存器的内容×16+偏移地址 =约定默认段地址×16+偏移地址 =越段地址×16+偏移地址 1、立即寻址 A→B,A就是PA(物理地址)可以直接给B 2、寄存器寻址 A→B,A(寄存器)的值是PA可以给B 3、直接寻址 A→B,A是EA,EA=确定的寄存器的值,由EA得到PA,然后给B 4、寄存器间接寻址 A→B,A是EA,EA=变动的寄存器的值,由EA得到PA,然后给B 5、寄存器相对寻址 A→B,A是EA,EA=变动的寄存器的值+DISP的值,由EA得到PA,然后给B 6、基址变址寻址 A→B,A是EA,EA=变动的寄存器的值+另一变动的寄存器的值,由EA得到PA ,然后给B 7、相对基址变址寻址 A→B,A是EA,EA=变动的寄存器的值+另一变动的寄存器的值+DISP的值, 由EA得到PA,然后给B 8、字符串寻址 A→B,A源PA,然后给B(目的pA) 理解寻址方式的关键是EA的值是什么和怎样由EA得到PA,方式4,5,6,7容易混淆,我这样解释可能不科学,但能达到明白它的意思就行。4和3的区别是EA=变动的寄存器的值,5在4的基础上加了DISP的值,6相当于2个5相加(EA=变动的寄存器的值+另一变动的寄存器的),7相当于5+6,哈哈,都什么和什么呀。 06 maggio 让Editplus支持汇编语言语法高亮显示-- 2006.5.6 By A.TNG
最近在看汇编,发现好多知识都还给老师了,得恶补回来。写了几行代码,发现SourceInsight感觉好不爽,还是用回最喜欢的Editplus。不过突然发现ep不支持汇编语言的语法高亮显示,很是郁闷,心想,如此强大的ep怎能如此弱,找了找ep的各个设置,发现在:工具-〉参数设置-〉文件-〉设置和语法 中有个可以设置语法高亮显示的选项,里头已经有了:cpp css html java js jsp ...。马上在网搜索了一个ASM的语法高亮设置,贴出来,分享一下,同时也感谢原作者的工作。
所需要做的是,打开ep,至对应的设置面板,选择添加,在描述中输入:ASM,在文件扩展名中输入:asm,然后在语法文件一栏选择对应的stx文件就好了。(asm的stx文件,就是把下面的东东保存为you_decide_the_name.stx)
#TITLE=ASM
; ASM syntax file written by kylin. ; This file is required for EditPlus to run correctly. #DELIMITER=,(){}[]-+*/=~!&|<>?:.
#QUOTATION1=' #QUOTATION2=" #CONTINUE_QUOTE=n #LINECOMMENT=; #ESCAPE=\ #CASE=y #PREFIX3=$ #PREFIX4=@ #PREFIX5=% #NUMBER_PATTERN=asm #SPECIAL_STX=asm #KEYWORD=Reserved words
db dw dd dq mov movsx movzx xchg push pusha pushad pop popa popad in out xlat lea lds les lfs lgs lss lahf sahf pushf pushfd popf popfd add sub adc sbb inc dec mul div imul idiv cbw cwd cwde cdq cmp neg daa das aaa aas aam aad and or xor not test shl sal rol ror rcl rcr shld shrd movs movsb movsw movsd cmps cmpsb cmpsw cmpsd scas scasb scasw scasd lods lodsb lodsw lodsd stos stosb stosw stosd ins insb insw insd outs outsb outsw outsd jmp jc jnc jz je jnz jne js jns jo jno jp jpe jnp jpo ja jneb jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jcxz jecxz loop loopz loope loopnz loopne ret retn retf int into iret iretd set clc stc cmc cld std cli sti hlt wait esc lock nop bt btc btr bts bsf bsr bound enter leave lar lsl lgdt lidt sgdt sidt ltr str lmsw smsw lldt sldt arpl clts verr verw DW DD DQ MOV MOVSX MOVZX XCHG PUSH PUSHA PUSHAD POP POPA POPAD IN OUT XLAT LEA LDS LES LFS LGS LSS LAHF SAHF PUSHF PUSHFD POPF POPFD ADD SUB ADC SBB INC DEC MUL DIV IMUL IDIV CBW CWD CWDE CDQ CMP NEG DAA DAS AAA AAS AAM AAD AND OR XOR NOT TEST SHL SAL ROL ROR RCL RCR SHLD SHRD MOVS MOVSB MOVSW MOVSD CMPS CMPSB CMPSW CMPSD SCAS SCASB SCASW SCASD LODS LODSB LODSW LODSD STOS STOSB STOSW STOSD INS INSB INSW INSD OUTS OUTSB OUTSW OUTSD JMP JC JNC JZ JE JNZ JNE JS JNS JO JNO JP JPE JNP JPO JA JNEB JAE JNB JB JNAE JBE JNA JG JNLE JGE JNL JL JNGE JLE JNG JCXZ JECXZ LOOP LOOPZ LOOPE LOOPNZ LOOPNE RET RETN RETF INT INTO IRET IRETD SET CLC STC CMC CLD STD CLI STI HLT WAIT ESC LOCK NOP BT BTC BTR BTS BSF BSR BOUND ENTER LEAVE LAR LSL LGDT LIDT SGDT SIDT LTR STR LMSW SMSW LLDT SLDT ARPL CLTS VERR VERW #KEYWORD=Register flat stdcall casemap none dup proto call local invoke eax ax ah al ebx bh bl bx ecx cx ch cl edx dx dh dl esi si edi di ebp bp esp sp carry overflow parity sign zero true false FLAT STDCALL CASEMAP NONE DUP PROTO CALL LOCAL INVOKE EAX AX AH AL EBX BH BL BX ECX CX CH CL EDX DX DH DL ESI SI EDI DI EBP BP ESP SP CARRY OVERFLOW PARITY SIGN ZERO TRUE FALSE #KEYWORD=Statements
386 model option data const stack code proc endp struc ends end include includelib if else elseif endif while endw repeat break continue until null 386 MODEL OPTION DATA CONST STACK CODE PROC ENDP STRUC ENDS END INCLUDE INCLUDELIB IF ELSE ELSEIF ENDIF WHILE ENDW REPEAT BREAK CONTINUE UNTIL NULL #KEYWORD=Description
ds cs es ss fs gs addr offset byte word dword ptr DS CS ES SS FS GS ADDR OFFSET BYTE WORD DWORD PTR #KEYWORD=Symbols
= : @ ( ) , . ; / + - * % # |
|
||||
|
|