Illustrate the square of a binomial

J, 9 bytes - 3 = 6

#~@|.*/#~

Inspired by @NBZ's APL answer, golfed down by @randomra. This defines a verb that takes in an array of numbers. It's used as follows:

   (#~@|.*/#~) 4 3
12 12 12 12  9  9  9
12 12 12 12  9  9  9
12 12 12 12  9  9  9
16 16 16 16 12 12 12
16 16 16 16 12 12 12
16 16 16 16 12 12 12
16 16 16 16 12 12 12

I also claim the 3-byte bonus, since an input of 0 produces sub-matrices of size zero:

   (#~@|.*/#~) 4 0
16 16 16 16
16 16 16 16
16 16 16 16
16 16 16 16
   (#~@|.*/#~) 0 3
9 9 9
9 9 9
9 9 9

Explanation

J has a definite edge in this challenge. In addition to eating array manipulation problems for breakfast, it prints 2D matrices in the correct format by default.

       #~  Replicate each number n in input n times
#~@|.      The same for reversed input
     */    Compute their multiplication table

Octave, 45 bytes - 3 = 42

s=@(m,n)[a=ones(n,1)*n;b=ones(m,1)*m].*[b;a]'

Explanation

This constructs two vectors (let's assume m = 4 and n = 3):

ones(n, 1) constructs an array of ones of size n x 1, so multiplying the ones by n we get:

ones(n, 1) * n => [3 3 3]' (where ' is transpose... n x 1 is a column vector)

a = [3 3 3  4 4 4 4]'   %// a is a column vector
b = [4 4 4 4  3 3 3]    %// b is a row vector

Then the vectors are multiplied in an element-wise fashion, with automatic broadcast expansion so that the 7-element vectors produce a 7x7-element matrix:

    [3] .* [4 4 4 4 3 3 3]
    [3]
    [3]
    [4]
    [4]
    [4]
    [4]

For example, multiplication of the first row of a by b gives:

    [3] .* [4 4 4 4 3 3 3] = [12 12 12 12  9  9  9]

And similarly for the remaining rows of a.

Output:

>> s(4,3)
ans =

   12   12   12   12    9    9    9
   12   12   12   12    9    9    9
   12   12   12   12    9    9    9
   16   16   16   16   12   12   12
   16   16   16   16   12   12   12
   16   16   16   16   12   12   12
   16   16   16   16   12   12   12

>> s(3,0)
ans =

   9   9   9
   9   9   9
   9   9   9

You can try it here on ideone


Dyalog APL, 10-3 = 7

Inspired* by this answer where the arguments are replicated and then used in a multiplication table:

⊖∘.×⍨(/⍨⎕)

Issues a prompt (⎕:) and evaluates any expression entered then. (For security reasons, this doesn't work on TryAPL but it does work on NGN/APL.)
/⍨ Replicates its argument itself times (/⍨4 3 ​⇔ 3 3 3 4 4 4 4)
∘.×⍨ Creates a multiplication table.
Flips upside down.

This happens to work on any length input (input is indented 6 spaces, output is at left margin):

      ⊖∘.×⍨(/⍨⎕)
⎕:
      ⍬      ⍝ Empty list (the square of nothing)
      ⊖∘.×⍨(/⍨⎕)
⎕:
      0      ⍝ 0​² = 0
      ⊖∘.×⍨(/⍨⎕)
⎕:
      0 1      ⍝ (0+1)​² = 1²
1
      ⊖∘.×⍨(/⍨⎕)
⎕:
      2 3      ⍝ (2+3)​² = 2² + 3²
6 6 9 9 9
6 6 9 9 9
6 6 9 9 9
4 4 6 6 6
4 4 6 6 6
      ⊖∘.×⍨(/⍨⎕)
⎕:
      1 2 3      ⍝ (1+2+3)​² = 1² + 2(1×2) + 2(1×3) + 2² + 2(2×3) + 3²
3 6 6 9 9 9
3 6 6 9 9 9
3 6 6 9 9 9
2 4 4 6 6 6
2 4 4 6 6 6
1 2 2 3 3 3
      ⊖∘.×⍨(/⍨⎕)
⎕:
      ⍳4    ⍝ Integers 1 through 4
4 8 8 12 12 12 16 16 16 16
4 8 8 12 12 12 16 16 16 16
4 8 8 12 12 12 16 16 16 16
4 8 8 12 12 12 16 16 16 16
3 6 6  9  9  9 12 12 12 12
3 6 6  9  9  9 12 12 12 12
3 6 6  9  9  9 12 12 12 12
2 4 4  6  6  6  8  8  8  8
2 4 4  6  6  6  8  8  8  8
1 2 2  3  3  3  4  4  4  4

*Originally, I had a different solution in mind: Each rectangle is created separately by creating a multiplication table for each combination of the two arguments. Then the four squares are mended together vertically and horizontally. It looks like this:

,/⍪⌿⊖∘.(,⍴×)⍨⎕

Prompt, as above.
,⍴×< Combine (,) the args and use that to shape () a rectangle filled with their product (×).
∘.(​…)⍨ Create a table where each cell is whatever is specified in (​…)
Flip vertically.
⍪⌿ Combine cells vertically.
,/ Combine cells horizontally.