不定长参数传递问题
void kprintf(char *fmt, ...) { char* p; va_list vl; va_start(vl, fmt); //_asm lea ax,word ptr [bp+6]; //_asm mov di,ax; for (p = fmt; *p; p++) { char c = *p; if (c == '$') break; if (c == '%') { //char v; char v = va_arg(vl, char); //_asm add di,2; //_asm mov al,byte ptr ss:[di-2]; //_asm mov v, al; _int10_0e(v); } else { _int10_0e(c); } } va_end(vl); }
对应汇编代码:
000302ab: ( ): push bp ; 55 000302ac: ( ): mov bp, sp ; 8bec 000302ae: ( ): sub sp, 0x0002 ; 83ec02 000302b1: ( ): push si ; 56 000302b2: ( ): push di ; 57 000302b3: ( ): lea ax, word ptr ss:[bp+6] ; 8d4606 000302b6: ( ): mov di, ax ; 8bf8 000302b8: ( ): mov si, word ptr ss:[bp+4] ; 8b7604 000302bb: ( ): jmp .+53 ; eb35 000302bd: ( ): mov al, byte ptr ds:[si] ; 8a04 000302bf: ( ): mov byte ptr ss:[bp-1], al ; 8846ff 000302c2: ( ): cmp byte ptr ss:[bp-1], 0x24 ; 807eff24 000302c6: ( ): jnz .+2 ; 7502 000302c8: ( ): jmp .+45 ; eb2d 000302ca: ( ): cmp byte ptr ss:[bp-1], 0x25 ; 807eff25 000302ce: ( ): jnz .+23 ; 7517 000302d0: ( ): add di, 0x0002 ; 83c702 000302d3: ( ): mov bx, di ; 8bdf 000302d5: ( ): mov al, byte ptr ds:[bx-2] ; 8a47fe 000302d8: ( ): mov byte ptr ss:[bp-2], al ; 8846fe 000302db: ( ): mov ah, 0x0e ; b40e 000302dd: ( ): mov al, byte ptr ss:[bp-2] ; 8a46fe 000302e0: ( ): mov bx, 0x000f ; bb0f00 000302e3: ( ): int 0x10 ; cd10 000302e5: ( ): jmp .+10 ; eb0a 000302e7: ( ): mov ah, 0x0e ; b40e 000302e9: ( ): mov al, byte ptr ss:[bp-1] ; 8a46ff 000302ec: ( ): mov bx, 0x000f ; bb0f00 000302ef: ( ): int 0x10 ; cd10 000302f1: ( ): inc si ; 46 000302f2: ( ): cmp byte ptr ds:[si], 0x00 ; 803c00 000302f5: ( ): jnz .-58 ; 75c6 000302f7: ( ): pop di ; 5f 000302f8: ( ): pop si ; 5e 000302f9: ( ): mov sp, bp ; 8be5 000302fb: ( ): pop bp ; 5d 000302fc: ( ): ret ; c3
另一个例子:
void args(char *prefix, ...) { va_list vl; char c; va_start(vl, prefix); c = va_arg(vl, char); _asm mov ah, 0eh; _asm mov al, c; _asm mov bx, 0fh; _asm int 10h; va_end(vl); }
对应汇编代码:
0E3B:0291 55 PUSH BP 0E3B:0292 8BEC MOV BP,SP 0E3B:0294 83EC02 SUB SP,+02 0E3B:0297 56 PUSH SI 0E3B:0298 8D4606 LEA AX,[BP+06] 0E3B:029B 8BF0 MOV SI,AX 0E3B:029D 83C602 ADD SI,+02 0E3B:02A0 8A44FE MOV AL,[SI-02] 0E3B:02A3 8846FF MOV [BP-01],AL 0E3B:02A6 B40E MOV AH,0E 0E3B:02A8 8A46FF MOV AL,[BP-01] 0E3B:02AB BB0F00 MOV BX,000F 0E3B:02AE CD10 INT 10 0E3B:02B0 5E POP SI 0E3B:02B1 8BE5 MOV SP,BP 0E3B:02B3 5D POP BP 0E3B:02B4 C3 RET
相关推荐
为了解决这种需求,C语言提供了三个宏:`va_start`、`va_end`以及`va_list`,这些宏允许我们在函数中处理不定数量的参数。 #### 宏定义解析 在VC++6.0的`stdarg.h`头文件中,包含了处理可变参数列表所需的关键宏...
### stdarg.h中三个宏va_start,va_arg和va_end的应用详解 在C语言中,经常需要编写能够接受可变数量参数的函数。一个典型的例子就是`printf`函数,它可以接受任意数量和类型的参数。为了支持这种功能,C语言提供了...
### C语言可变参数机制详解:`va_list`与`vsnprintf`及`printf`实现 #### 引言 在C语言编程中,我们经常使用`printf`函数来输出各种格式的数据,但你是否曾思考过,这个看似简单的函数背后隐藏着怎样的复杂性?`...
写可变参数的C函数要在程序中用到以下这些宏: 代码如下:void va_start( va_list arg_ptr, prev_param );type va_arg( va_list arg_ptr, type );void va_end( va_list arg_ptr );va在这里是variable-argument(可变...
在C语言中,`va_arg`是一个非常重要的函数宏,它是可变参数列表(Variable Argument List,也称为 variadic function)处理的关键组成部分。标题“va_arg_c_”可能指的是一个文档,专门探讨了如何在C语言中使用`va_...
要使用`_va_list`,你需要包含`<stdarg.h>`头文件,然后利用`va_start`, `va_arg`和`va_end`宏来初始化和操作`_va_list`变量。 - `va_start`: 初始化`_va_list`变量,使其指向可变参数列表的第一个参数。 - `va_arg...
1. 因为va_start, va_arg, va_end等定义成宏,所以它显得很愚蠢, 可变参数的类型和个数完全在该函数中由程序代码控制,它并不能智能地识别不同参数的个数和类型。 2. 另外还有一个问题,因为编译器对可变参数的函数...
这主要通过一组预定义的宏来实现,包括`va_list`、`va_start`、`va_arg`和`va_end`,这些宏定义在`stdarg.h`头文件中。下面我们将详细探讨这些宏的用途和工作原理。 1. `va_list`: `va_list`是一个类型定义,它...
本文讨论了C语言中可变参数的用法,包括如何写一个简单的可变参数的C函数,如何使用可变参数宏va_start、va_arg和va_end,以及可变参数在编译器中的处理。 一、写一个简单的可变参数的C函数 在C语言中,某些函数...
C语言标准库提供了处理可变参数的一系列宏,包括`va_list`、`va_start`、`va_arg`和`va_end`等。这些宏可以帮助开发者处理可变参数函数中的参数。 - **`va_list`**: 定义一个类型,用于存储指向可变参数列表的指针...
可变参数函数的实现主要包括几个宏:va_list, va_start, va_arg, va_end。下面将详细讲解这些宏以及它们的用法: 1. va_list: 这个类型用于声明一个变量,该变量会被用来遍历参数列表。在stdarg.h中,va_list被定义...
本文将深入探讨如何使用`va_list`、`va_start`、`va_arg`和`va_end`这四个宏来处理这种特殊的参数传递。 `va_list`是一个类型定义,它定义了一个可以存储变长参数列表中下一个参数地址的类型。在函数中,我们需要...
va_start宏用于初始化可变参数表,va_arg宏用于取得当前的可变参数,va_end宏用于结束可变参数的使用。 va_start宏的原型为:void va_start(va_list ap, prev_param),其中ap是指向可变参数表的指针,prev_param是前...
2. 使用`stdarg.h`库(C)或`<cstdarg>`库(C++)处理可变参数的三个关键宏:`va_start`、`va_arg`和`va_end`。 3. 如何在函数中定义和使用`va_list`,以及如何正确处理参数类型。 4. 通过实例展示了如何创建一个...
这个头文件中定义了`va_list`、`va_start`、`va_arg`和`va_end`宏,它们是处理可变参数列表的关键。下面逐一解释这些宏的作用: 1. `va_list`: 这是一个类型定义,用来声明一个可变参数列表的变量。例如:`va_list ...
在C语言中,通过宏`va_start`、`va_arg`和`va_end`来处理这些可变参数。这些宏定义在`stdarg.h`头文件中,因此编写可变参数函数时需要包含此头文件。 #### 宏定义解析 1. **`va_start`**: 初始化可变参数列表的...
这种机制是通过一组特殊的宏实现的,包括`va_start`、`va_arg`、`va_end`和`va_copy`。本文将详细探讨这些宏的用法,并通过几个实际例子来阐述其工作原理。 ### 一、`va_start`宏 `va_start`是用于初始化可变参数...
- **内存管理**: 避免对`va_list`指针进行不当操作,确保在使用完毕后调用`va_end`。 #### 结论 C语言的变参函数设计提供了一种灵活的方式来处理参数数量不确定的情况,尤其是在需要处理多个类型和数量不定的参数...
C语言中的va函数,也就是可变参数函数(variable argument function),允许函数接收不定数量的参数,这种机制为函数调用提供了极大的灵活性。在C/C++标准库中,printf()和scanf()系列函数就是典型的可变参数函数,...