📄 libc.asm
字号:
%ifdef __PIC__ __GET_GOT mov ebx,__EXT_VAR(__envp) mov ebx,[ebx]%else mov ebx,[__envp]%endif mov edx,edi cld xor eax,eax or ecx,byte -1 repne scasb not ecx dec ecx mov eax,ecx.next_var: mov ecx,eax mov esi,edx mov edi,[ebx] test edi,edi jz .ret rep cmpsb jz .found add ebx,byte 4 jmps .next_var.found: inc edi ;assume = is next.ret: mov [__eax],edi popa ret;size_t strlen(const char *s);;<EDX *s;;>EAXstrlen: push edx __ADJUST_CDECL3 4*1,eax mov edx,eax.real:%if __OPTIMIZE__=__O_SPEED__ push ecx test dl,3 jz .boucle cmp byte[eax],0 jz .strfi cmp byte[eax+1],0 jz .ret1 cmp byte[eax+2],0 jnz .align add eax,byte 2 jmps .strfi.align: add eax,byte 3 and eax,byte -4.boucle: ;normally the whole loop is 7 cycles (for 8 bytes) mov ecx,dword[eax] test cl,cl jz .strfi test ch,ch jz .ret1 test ecx,0xFF0000 jz .ret2 shr ecx,24 jz .ret3 mov ecx,dword[eax+8] test cl,cl jz .ret4 test ch,ch jz .ret5 test ecx,0xFF0000 jz .ret6 add eax,byte 8 shr ecx,4 jnz .boucle dec eax jmps .strfi.ret1: inc eax jmps .strfi.ret2: add eax,byte 2 jmps .strfi.ret3: add eax,byte 3 jmps .strfi.ret4: add eax,byte 4 jmps .strfi.ret5: dec eax.ret6: add ecx,byte 6.strfi: sub eax,edx pop ecx%else ;__O_SIZE__ xor eax,eax.boucle: cmp byte[edx+eax],1 inc eax jnc .boucle dec eax%endif ;__OPTIMIZE__ pop edx ret;itoa (unsigned long value, char *string, int radix);;print 32 bit number as binary,octal,decimal,or hexadecimal value;;<EAX unsigned long value;<EDI char *string;<ECX base (2, 8, 10, 16, or another one)itoa: pusha mov edi,edx __ADJUST_CDECL3 4*8,eax,edi,ecx.real:.now: call .printB mov byte [edi],0 ;zero terminate the string popa ret.printB: sub edx,edx div ecx test eax,eax jz .print0 push edx call .printB pop edx.print0: add dl,'0' cmp dl,'9' jle .print1 add dl,0x27.print1: mov [edi],dl inc edi ret;int sprintf(char *str, const char *format, ...);;sprintf: pusha lea edx,[esp + 4*8 + 12] ;preload argument (dangerous?) mov esi,[esp + 4*8 + 8] ;*format mov edi,[esp + 4*8 + 4] ;*str push edi cld.boucle: lodsb test al,al jz .out_pf cmp al,'%' jz .gest_spec; cmp al,'\' ;is it really needed?; jz .gest_spec2 ;or compiler expands these characters?.store: stosb jmps .boucle.gest_spec: mov ebx,[edx] lodsb _mov ecx,10 cmp al,'d' jz .gestf _mov ecx,16 cmp al,'x' jz .gestf _mov ecx,8 cmp al,'o' jz .gestf _mov ecx,2 cmp al,'b' jz .gestf cmp al,'c' jz .store cmp al,'s' jnz .boucle test ebx,ebx ;NULL check jz .allok.copyit: ;copy string in args to output buffer mov al,[ebx] test al,al ;string is null terminated jz .allok stosb inc ebx jmps .copyit.gestf: pusha mov eax,ebx call itoa.printB mov byte [edi],0 ;zero terminate the string popa.stl: cmp byte [edi],1 inc edi jnc .stl dec edi.allok: add edx,byte 4 jmps .boucle;.gest_spec2:; lodsb; mov ah,__n; cmp al,'n'; jz .s2; mov ah,__t; cmp al,'t'; jnz .boucle;.s2:; mov al,ah; stosb; jmps .boucle.out_pf: xor al,al stosb pop edx sub edi,edx dec edi ;do not write trailing 0 mov [__eax],edi popa ret;int printf(const char *format, ...);;uses rather dangerous approachprintf:%define _sf 0x1000 sub esp,_sf ;create buffer (dangerous!!) pusha mov ebp,[esp + 4 * 8 + _sf] ;save return address lea esi,[esp + 4 * 8] ;here will our buffer begin add esp,4 * 8 + _sf ;rewind stack back mov [esp],esi ;replace return address with buffer call sprintf mov [esp],ebp ;restore return address sub esp,4 * 8 + _sf ;substitute stack sys_write STDOUT,esi,eax mov [__eax + _sf],eax popa add esp,_sf ret%undef _sf;int inet_aton(const char *cp, struct in_addr *inp);;convert IP address ascii string to 32 bit network oriented;;<ESI *cp;<EDI *inp;;>EAXinet_aton: push esi push edi push edx mov esi,eax mov edi,edx __ADJUST_CDECL3 4*3,esi,edi cld _mov ecx,4; convert xx.xx.xx.xx to network notation.conv: xor edx,edx.next: lodsb sub al,'0' jb .loop1 add edx,edx lea edx,[edx+edx*4] add dl,al jmps .next.loop1: mov al,dl stosb loop .next xor eax,eax ;assume address was valid pop edx pop edi pop esi ret;long strtol(const char *nptr, char **endptr, int base);;convert string in npt to a long integer value;according to given base (between 2 and 36);if enptr if not 0, it is the end of the string;else the string is null-terminated;;<EDI const char *nptr;<ESI char **endptr, or 0 if string is null-terminated;<ECX int base (2, 8, 10, 16, or another one max=36);;>EAXstrtol: push edi push esi push ebx push ecx mov edi,eax mov esi,edx __ADJUST_CDECL3 4*4,edi,esi,ecx test ecx,ecx jnz .base_ok _mov ecx,10 ;default base to use.base_ok: xor eax,eax xor ebx,ebx.parse1: cmp byte [edi],32 jnz .parse2 inc edi jmps .parse1.parse2: cmp word[edi],'0x' jnz .next _mov ecx,16 add edi,byte 2.next: mov bl,[edi] sub bl,'0' jb .done cmp bl,9 jbe .ok sub bl,7 cmp bl,35 jbe .ok sub bl,32.ok: imul ecx add eax,ebx inc edi cmp edi,esi jnz .next.done: pop ecx pop ebx pop esi pop edi ret;;unused functions;%macro _UNUSED_ 0;;convert 32 bit number to hex string;;>EAX;<EDILongToStr: pushad sub esp,4 mov ebp,esp mov [edi],word "0x" inc edi inc edi mov esi,edi push esi mov [ebp],eax _mov ecx,16 ;10 - decimal _mov esi,0.l1: inc esi xor edx,edx mov eax,[ebp] div ecx mov [ebp],eax mov al,dl;dec convertion; add al,'0'; add al,0x90; daa; adc al,0x40; daa;hex convertion cmp al,10 sbb al,0x69 das stosb xor eax,eax cmp eax,[ebp] jnz .l1 stosb pop ecx xchg ecx,esi shr ecx,1 jz .l3 xchg edi,esi dec esi dec esi.l2: mov al,[edi] xchg al,[esi] stosb dec esi loop .l2.l3: add esp,4 popad ret;;convert string to 32 bit number;;<EDI;>EAXStrToLong: push ebx push ecx push edi _mov eax,0 _mov ebx,10 _mov ecx,0.next: mov cl,[edi] sub cl,'0' jb .done cmp cl,9 ja .done mul bx add eax,ecx; adc edx,0 ;for 64 bit inc edi jmp short .next.done: pop edi pop ecx pop ebx retstrlen2:%if __OPTIMIZE__=__O_SIZE__ push edi mov edi,[esp + 8] mov eax,edi dec edi.l1: inc edi cmp [edi],byte 0 jnz .l1 xchg eax,edi sub eax,edi pop edi%else; (NK); note: below is classic variant of strlen; if not needed to save ecx register then size of classic code; will be same as above ; remark: fastcall version of strlen will on 2 bytes less than cdecl push esi push ecx mov esi,[esp + 12] xor eax,eax or ecx,-1 repne scasb not ecx mov eax,ecx dec eax pop ecx pop esi%endif _leave%endmacro ;_UNUSED_UDATASEG;;store them within caller's image;common errno 4 ;guess whatcommon __cc 4 ;calling convention (how many registers for fastcall) ;0 = cdeclcommon __envp 4 ;envp, for getenv()END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -