diff options
author | Jaroslavas Počepko <jp@webmaster.ms> | 2011-08-30 14:43:54 +1000 |
---|---|---|
committer | Alex Brainman <alex.brainman@gmail.com> | 2011-08-30 14:43:54 +1000 |
commit | ae891b55289c4147d2c6271759f97ea00246bf17 (patch) | |
tree | 1c9a1d6e38c45e2d4350572eb089993ad9683394 | |
parent | 22d5f9aae364f8d9d77fa67abf791b7d8046af56 (diff) | |
download | go-ae891b55289c4147d2c6271759f97ea00246bf17.tar.gz go-ae891b55289c4147d2c6271759f97ea00246bf17.zip |
windows/386: clean stack after syscall (it is necessary after call cdecl functions and does not have an effect after stdcall)
Result of discussion here: http://groups.google.com/group/golang-nuts/browse_thread/thread/357c806cbb57ca62
R=golang-dev, bradfitz, alex.brainman, hectorchu, rsc
CC=golang-dev
https://golang.org/cl/4961045
-rw-r--r-- | src/pkg/runtime/syscall_windows_test.go | 61 | ||||
-rw-r--r-- | src/pkg/runtime/windows/386/sys.s | 5 |
2 files changed, 65 insertions, 1 deletions
diff --git a/src/pkg/runtime/syscall_windows_test.go b/src/pkg/runtime/syscall_windows_test.go new file mode 100644 index 0000000000..aec85ec167 --- /dev/null +++ b/src/pkg/runtime/syscall_windows_test.go @@ -0,0 +1,61 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime_test + +import ( + "syscall" + "unsafe" + "testing" +) + +func TestStdCall(t *testing.T) { + type Rect struct { + left, top, right, bottom int32 + } + + h, e := syscall.LoadLibrary("user32.dll") + if e != 0 { + t.Fatal("LoadLibrary(USER32)") + } + p, e := syscall.GetProcAddress(h, "UnionRect") + if e != 0 { + t.Fatal("GetProcAddress(USER32.UnionRect)") + } + + res := Rect{} + expected := Rect{1, 1, 40, 60} + a, _, _ := syscall.Syscall(uintptr(p), + 3, + uintptr(unsafe.Pointer(&res)), + uintptr(unsafe.Pointer(&Rect{10, 1, 14, 60})), + uintptr(unsafe.Pointer(&Rect{1, 2, 40, 50}))) + if a != 1 || res.left != expected.left || + res.top != expected.top || + res.right != expected.right || + res.bottom != expected.bottom { + t.Error("stdcall USER32.UnionRect returns", a, "res=", res) + } +} + +func TestCDecl(t *testing.T) { + h, e := syscall.LoadLibrary("user32.dll") + if e != 0 { + t.Fatal("LoadLibrary(USER32)") + } + p, e := syscall.GetProcAddress(h, "wsprintfA") + if e != 0 { + t.Fatal("GetProcAddress(USER32.wsprintfA)") + } + + var buf [50]byte + a, _, _ := syscall.Syscall6(uintptr(p), + 5, + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(syscall.StringBytePtr("%d %d %d"))), + 1000, 2000, 3000, 0) + if string(buf[:a]) != "1000 2000 3000" { + t.Error("cdecl USER32.wsprintfA returns", a, "buf=", buf[:a]) + } +} diff --git a/src/pkg/runtime/windows/386/sys.s b/src/pkg/runtime/windows/386/sys.s index 111e3d94c3..94aed83f06 100644 --- a/src/pkg/runtime/windows/386/sys.s +++ b/src/pkg/runtime/windows/386/sys.s @@ -12,6 +12,7 @@ TEXT runtime·asmstdcall(SB),7,$0 MOVL $0, 0x34(FS) // Copy args to the stack. + MOVL SP, BP MOVL wincall_n(DX), CX // words MOVL CX, BX SALL $2, BX @@ -21,9 +22,11 @@ TEXT runtime·asmstdcall(SB),7,$0 CLD REP; MOVSL - // Call stdcall function. + // Call stdcall or cdecl function. + // DI SI BP BX are preserved, SP is not MOVL wincall_fn(DX), AX CALL AX + MOVL BP, SP // Return result. MOVL c+0(FP), DX |