将参数推送到堆栈的宏

时间:2015-06-16 04:14:23

标签: visual-c++ assembly macros

我一直在研究一个有趣的小项目来讨论如何调用函数,我需要一个宏来推送参数,因为为这个混淆的调用的每个实例手动推送参数将非常耗时。

到目前为止,这是我的代码:

AVAudioPlayer *somePlayer = [AVAudioPlayer new];
__autoreleasing NSError* error;
somePlayer = [somePlayer initWithContentsOfURL:[[[MPMusicPlayerController systemMusicPlayer] nowPlayingItem] valueForProperty:MPMediaItemPropertyAssetURL] error:&error];
somePlayer.currentTime = [[MPMusicPlayerController systemMusicPlayer] currentPlaybackTime];
somePlayer.volume = 0;
[somePlayer play];
[somePlayer setMeteringEnabled:YES];
[somePlayer updateMeters];
NSMutableArray* amps = [NSMutableArray array];
if (error != nil) {
    NSLog(@"error: %@", error.debugDescription);
}
for (int i = 0; i < somePlayer.numberOfChannels; i++) {
    [amps addObject:@(([somePlayer peakPowerForChannel:i] + 160.0) / 160.0)];
    NSLog(@"Amplitude: %f db for channel %i", [somePlayer averagePowerForChannel:i], i);
}
float amp = 0;
for (NSNumber *x in amps) {
    amp += [x floatValue];
}
amp /= amps.count;
NSLog(@"amp: %f", amp);

我觉得这是不可能的,如果我错了,请纠正我......

1 个答案:

答案 0 :(得分:0)

如果您仍然对使用 Visual C ++ 编译器感兴趣,可以尝试使用此代码

#define pushargs(...) for (unsigned int _esp; ;) _esp = varcount(), _esp =(_esp-varcount(__VA_ARGS__))>>2, pushargs_c(_esp, __VA_ARGS__ ); 



unsigned int __declspec(naked) __forceinline varcount(...)
{
    __asm mov eax, esp;
    __asm ret;
}

unsigned int __declspec(naked) __forceinline pushargs_c(unsigned int count, ...)
{
    __asm mov eax, DWORD PTR [esp+04h]
    __asm dec eax
    __asm shl eax, 2
    __asm sub esp, eax
    __asm push DWORD PTR [esp+eax]
    __asm ret;
}

我的Visual Studio版本(2013 express)即使使用__forceinline也不会内联通话。
此代码不可移植并且是特定于实现的,我发现它与我的VC ++编译器一起使用,即使在发布模式下也可能在重度优化或新的Visual Studio版本中中断!

试一试,您可以按预期使用pushargs宏。 pushargs_c更可靠,但要求第一个参数为剩余参数的数量(即pushargs_c(5, 1,2,3,4,5))。